2013-07-26 7 views
5

Как мне выполнить делегирование событий в стиле jQuery с помощью простого JavaScript в Hammer.js? Например:Событие делегирование с Hammer.js

Hammer(document).on('tap', '.item', function() { 
    console.log('tapped') 
}) 

Возможно ли это непосредственно или я должен сам сделать делегацию?

+0

Осматривая цель - будет ** ** только работа, если нажать на элемент с '.item'. Но если внутри этого '.item' есть другой элемент, и вы нажимаете на этот внутренний элемент - проверка цели не поможет. вам нужно будет отсканировать своего родителя (это то, что предоставили другие ответы) - что именно вы хотели в своем вопросе '$ .on ('tap', '.item', function() {...}'. with jquery - используя ваш код, вам будет предоставлена ​​правильная информация EVEN, если вы щелкнули во внутреннем элементе на '.item' –

+0

Как вы можете видеть здесь - проверка цели покажет вам кнопку, которая не является' .item' http://jsbin.com/hobenunale/1/edit?html,js,output - в то время как jquery показывает вам удаленный элемент. –

ответ

2

Вам просто нужно проверить объект target объекта Event, который передан в ваш обработчик.

Here's a demo.

+0

Это не то, что хотел OP. –

+0

@Royi, действительно? Потому что он принял этот ответ .. . * 4 года назад * –

+0

Имеет ли значение? Мне нужно было использовать 'Hammer (document) .on ('tap', '.item', function() { console.log ('tapped') })' - И цель не была помощником :-) –

3

Я использую следующую функцию для проверки, является ли цель делегатом.

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, потому что я использую его много и с более сложными селекторами.

Использование:

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> 

Андре потерпит неудачу, потому что здесь target является [div.text] и не имеет свой класс.

Для вышеуказанного использования _getDelegate, давайте скажем $element = $("#parent"). Если вы набрали слово «Тест» 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'); 
} 

Есть еще много недостатков с этим. Весь индекс классаName - плохая идея, потому что классы могут быть подстроками друг друга, например. «myClass» и «myClass2». Кроме того, мой код делает предположение, что все ваши подэлементы расположены в пределах их родителей.

+0

Приятный, но полезный пример вашего метода '_isDelegate' будет полезен и/или документация параметров. Кроме того, не было бы '_getDelegate' более точным именем, так как оно не возвращает логическое значение? :) – Lambart

+0

Спасибо. Я добавил пример использования, который просто использует jquery для обработчика, хотя хорошо, что вы добавили использование hammer's(). Я тоже изменил имя функции. Я уверен, что это был isDelegate, потому что, когда я его написал, я не использовал элемент в обработчике. Когда я хотел элемент, было легко изменить его, чтобы вернуть элемент, но забыл изменить имя функции. – Jools

3

Вдохновленный ответом Джулса, вот что я придумал. Я не потрудился с решением pure-JS - на самом деле, он предназначен для использования с Backbone.View, но легко адаптируется к другим ситуациям.

Он перестанет подниматься по дереву узлов, когда достигнет корневого элемента View (this.el). Начиная с целевого объекта, идентифицированного событием HammerJS, он будет искать первый элемент, соответствующий указанному селектору, и возвращает undefined, если такой элемент не найден.

Для использования в среде, отличной от базовой, просто передайте ссылку на элемент ограничения/содержания в качестве третьего аргумента (как в решении 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(), если ваше вид разрушен!)

+0

Странно, но OP принял ответ, который не решает проблему. Цель не совпадает с элементом делегированного события –

-1

Продолжая @ решение Lambarr в - Машинопись:

private delegateBind(rootElement:Node,e, selector:string, handler: (target:any) => any) 
    { 

    let target=e.target; 
    let o = { 

     getEventDelegate: function() 
     { 
     var delegate; 

     while (target && target != rootElement) 
     { 
      delegate = jQuery(target).filter(selector)[0]; 
      if (delegate) 
      { 
      return delegate; 
      } 

      target = target.parentNode; 
     } 
     return undefined; 
     } 

    }; 

    target = o.getEventDelegate(); 
    if (target) 
    { 
     handler(target); 
    } 
    } 

Использование:

private registerDocumentclick() 
    { 

    Hammer(this.document).on('tap', e => 
     this.delegateBind(this.document,e,'.article', (elm) => console.log(elm.classList)) 

    ); 
    } 
Смежные вопросы