Hammer.js でプレーンな JavaScript を使用して jQuery スタイルのイベント委任を行うにはどうすればよいですか? 例えば:
Hammer(document).on('tap', '.item', function () {
console.log('tapped')
})
これは直接可能ですか、それとも委任を自分で行う必要がありますか?
Hammer.js でプレーンな JavaScript を使用して jQuery スタイルのイベント委任を行うにはどうすればよいですか? 例えば:
Hammer(document).on('tap', '.item', function () {
console.log('tapped')
})
これは直接可能ですか、それとも委任を自分で行う必要がありますか?
Jools の答えに触発されて、ここに私が思いついたものがあります。私は純粋な JS ソリューションを気にしませんでした。実際、これは で使用することを目的としていますが、Backbone.View
他の状況にも簡単に適応できます。
ビューのルート要素 ( ) に到達すると、ノード ツリーの上昇が停止しますthis.el
。HammerJS イベントによって識別されたターゲットから開始して、指定されたセレクターに一致する最初の要素を探し、そのundefined
ような要素が見つからない場合は戻ります。
非バックボーン環境で使用するには、制限/包含要素への参照を 3 番目の引数として渡し (Jools のソリューションのように)、それを使用して を置き換えthis.el
ます。
/**
* @param {Node}target - the target of the received event
* @param {String}selector - any jQuery-compatible selector
*/
getEventDelegate: function (target, selector) {
var delegate;
while (target && target != this.el) {
delegate = $(target).filter(selector)[0];
if (delegate) {
return delegate;
}
target = target.parentNode;
}
return undefined;
}
コールバック関数がある場合、次のonTap
ようになります。
/**
* @param {Event}ev
*/
onTap: function (ev) {
var target = this.getEventDelegate(ev.target, "#desiredTarget");
if (target) {
// TODO something with the target...
}
}
そして、それをすべて接続するには、次のようなものが必要です...
this._hammer = new Hammer(this.el);
this._hammer.on('tap', _.bind(this.onTap, this));
this._hammer.destroy()
(ビューが破棄されたときに呼び出すことを忘れないでください!)
次の関数を使用して、ターゲットがデリゲートかどうかをテストします。
function _getDelegate(selector, target, currentTarget) {
var delegate = null;
while (target && target != currentTarget) {
delegate = $(target).filter(selector)[0];
if (delegate)
return delegate;
target = target.parentNode;
}
return delegate;
}
jquery フィルターを使用しているのは、jquery フィルターを頻繁に使用し、より複雑なセレクターを使用しているためです。
使用法:
var delegationSelector = ".child";
$element.hammer()
$element.on("tap", function handler(event){
var delegate = _getDelegate(delegationSelector, event.target, event.currentTarget);
if(delegate){ // or if(!delegate) return;
// Your handler code
}
});
これはすべてのセレクターで機能するわけではありませんが、「ターゲット」に子要素がある場合でも機能するという点で、アンドレよりも優れていると思います。例えば
<div id="parent">
<div class="child">
<div class="text">Test</div>
</div>
</div>
André's はここで失敗します。これtarget
は、[div.text]
and にクラスがないためです。
上記の _getDelegate の使用法について、たとえば$element = $("#parent")
. 「Test」という単語をタップするevent.target
と、[div.text]
(タップした場所) とevent.currentTarget
([div.parent]
ハンドラーが登録されている場所) になります。_getDelegate
これらのパラメーターを使用して呼び出すと[div.child]
、ハンドラー コードを実行する必要があることがわかります。
純粋な JS バージョンの場合は、次のようなものが必要です。親をループして、何かにヒットしたかどうかを確認します。
var delegate;
var target = e.target; // e.g. Inner div
var currentTarget = e.currentTarget // e.g. #parent
while(target && target != currentTarget){
if(target.className.indexOf('child')!=-1){
delegate = target;
break;
}
target = target.parentNode;
}
if( delegate ) {
console.log('delegated tap received');
}
これにはまだ多くの欠陥があります。クラスは、「myClass」と「myClass2」など、互いの部分文字列になる可能性があるため、className のインデックス全体を使用することはお勧めできません。また、私のコードは、すべてのサブ要素が親内に配置されていることを前提としています。
target
ハンドラーに渡された Event オブジェクトを検査するだけです。
ここにデモがあります。