我正在尝试编写自己的事件委托系统,它工作得很好,除了我将它附加到元素后无法删除它!我一直在试图解决这个问题。任何帮助将不胜感激。
代码在笔中:http://codepen.io/anon/pen/BjyZyV?editors=101
以及下面:
<ul id="parent">
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
<li class="item">Lorum</li>
</ul>
Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
function isDescendant(parents, child) {
for (var i = 0; i < parents.length; i++) {
var node = child.parentNode;
while (node !== null) {
if (node === parents[i]) {
return true;
}
node = node.parentNode;
}
}
return false;
}
function eventCallback(e) {
if (e.target && e.target.matches(this.options.selector)) {
this.options.callback.call(this, e);
} else if (isDescendant(this.parent.querySelectorAll(this.options.selector), e.target)) {
this.options.callback.call(this, e);
}
}
var MyEvent = {
register: function register(options) {
this.parent = document.querySelector(options.parentSelector);
this.options = options;
this.parent.addEventListener(options.event, eventCallback.bind(this), false);
return this;
},
unregister: function unregister(options) {
this.parent = document.querySelector(options.parentSelector);
this.parent.removeEventListener(options.event, eventCallback, false);
return this;
}
};
myEvent = Object.create(MyEvent);
myEvent.register({
event: 'click',
parentSelector: '#parent',
selector: '.item',
callback: function(e) {
alert('clicked!');
}
});
myEvent.unregister({
event: 'click',
parentSelector: '#parent'
});
答案 0 :(得分:1)
问题出在bind()
,它会返回一个新功能
从文档
bind()方法创建一个新函数,当被调用时,它具有它 此关键字设置为提供的值,具有给定的序列 调用新函数时提供的任何参数。
因此,每当您致电bind
时,您都会获得一个全新的功能,例如
this.parent.addEventListener(options.event, eventCallback.bind(this), false);
与
相同var brandNewFunction = eventCallback.bind(this); // creates new function
this.parent.addEventListener(options.event, brandNewFunction, false);
所以你根本没有传递函数eventCallback
,你传递了一个新函数,因此无法用
this.parent.removeEventListener(options.event, eventCallback, false);
因为你从未传递过eventCallback
,并且removeEventListener
的功能必须相同才能删除听众。
解决方案当然是这样称呼它
this.parent.addEventListener(options.event, eventCallback, false);
并找到一些其他聪明的方法来传递你的选择等。