更改事件的currentTarget以进行事件委派

问题描述 投票:0回答:2

我正在尝试在网站上添加一些委托事件,但是我没有一个与传统侦听器回调签名(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)但目前未设置targetcurrentTarget

当然,这需要在普通js中使用。

谢谢!

javascript dom-events
2个回答
0
投票

使用.call()以元素引用作为this的值来调用回调:

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

在回调中,this将引用“启动器”,并且您不需要其他参数。


0
投票

您可以将所需元素作为自定义属性添加到事件对象,如下所示:

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,但尚未经过大量测试,并且可能会因某些特定事件而失败。

© www.soinside.com 2019 - 2024. All rights reserved.