我正在尝试在网站上添加一些委托事件,但是我没有一个与传统侦听器回调签名(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中使用。
谢谢!
使用.call()
以元素引用作为this
的值来调用回调:
if ( e.target && ( initiator = e.target.closest( target ) ) ) {
callback.call(initiator, e);
}
在回调中,this
将引用“启动器”,并且您不需要其他参数。
您可以将所需元素作为自定义属性添加到事件对象,如下所示:
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,但尚未经过大量测试,并且可能会因某些特定事件而失败。