无法从我自己的事件委托系统中删除事件
Cannot removing an event from my own event delegation system
我正在尝试编写自己的事件委托系统,它运行良好,只是一旦我将事件附加到元素就无法删除它!我一直在努力弄清楚这一点。任何帮助将不胜感激。
代码在笔中: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>
Javascript
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'
});
问题出在 bind()
,它 returns 一个新函数。
来自文档
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
所以每次你调用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);
并找到其他一些巧妙的方法来传递您的选项等。
我正在尝试编写自己的事件委托系统,它运行良好,只是一旦我将事件附加到元素就无法删除它!我一直在努力弄清楚这一点。任何帮助将不胜感激。
代码在笔中: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>
Javascript
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'
});
问题出在 bind()
,它 returns 一个新函数。
来自文档
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
所以每次你调用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);
并找到其他一些巧妙的方法来传递您的选项等。