изменить currentTarget события для делегирования события - PullRequest
0 голосов
/ 04 марта 2020

Я пытаюсь добавить событие делегата на веб-сайт, и у меня не получается функция, которая соответствует сигнатуре обратного вызова традиционного слушателя (function( event ) {}), и для получения текущего элемента прослушивания мне нужно передать другой параметр в функцию.

Вот чего мне удалось добиться:

const delegate = function( element, events, target, callback ) {
    events.split( " " ).forEach( event => element.addEventListener( event, function( e ) {
        let initiator;
        if ( e.target && ( initiator = e.target.closest( target ) ) ) {
            callback( e, initiator );
        }
    } ) );
};

let count = 0;

delegate( document, "click", ".js-test-delegate", function( event, elem ) {
  elem.innerHTML = `you click on this container ${++count} time(s)`;
} );


const div = document.createElement("div")
div.classList.add( "js-test-delegate" );

document.querySelector( ".container" ) .appendChild( div );
.container{
  width: 300px;
  height: 300px;
  background: rgba(256,0,0,.2);
}

.js-test-delegate{
  width: 100px;
  height: 100px;
  position: relative;
  top: 100px;
  left: 100px;
  background: rgba(0,256,0,.2);
}
<div class="container"></div>

Есть ли способ передать этот элемент elem в событие, чтобы он заменил свойство currentTarget для упрощения поведения?

Я пытаюсь изменить Event, но свойства типа currentTarget доступны только для чтения или клонирования event = new Event( "click", e), но target и currentTarget не установлены в данный момент.

И из Конечно это должно быть ванильным js.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 04 марта 2020

Вы можете добавить требуемый элемент к объекту события как пользовательское свойство, например:

const delegate = function( element, events, target, callback ) {
    events.split(" ").forEach(event => element.addEventListener(event, function(e) {
       let initiator = e.target.closest(target);
       if (e.target && initiator) {
           e.initiator= initiator;
           callback(e);
           // If you want also to bind this to the initiator, call:
           // callback.call(initiator, e);
       }
    }));
};

Теперь вы можете прочитать пользовательское свойство из event объекта:

delegate(document, 'click', '.js-test-delegate'", function(e) {
  e.initiator.innerHTML = `you click on this container ${++count} time(s)`;
});

Обойти защиту только для чтения для свойств объекта event возможно, но это не тривиальная задача. Вам нужно будет создать новый объект, добавить в него все свойства и дополнительно связать this значение всех методов с исходным событием. Вот что делает fiddle , но это не так много проверено и может завершиться ошибкой с некоторыми конкретными c событиями.

0 голосов
/ 04 марта 2020

Используйте .call() для вызова обратного вызова со ссылкой на элемент в качестве значения this:

    if ( e.target && ( initiator = e.target.closest( target ) ) ) {
        callback.call(initiator, e);
    }

В обратном вызове this будет ссылаться на «инициатора», и вы выиграли » Тебе нужен другой параметр.

...