1,问题出现场景:
有得时候我们要所点击元素的父级,例如这种情况,
ul
li
span
...
我们点击span(多数会点击到),其实是想对 li 进行操作,但是由于是事件委托,不得不把事件放到 ul 上(可能是要少写代码)。所以便有如下代码。
上面一层是我用来测试的html
下面是 原生 js 实现,其实还可以参考下 jquery 的实现方式。类似于这种,
$('ul').on('click', 'li', function (e) {}) // 这样绑定的话 e.currentTarget 就是 li
但是我没有jq的环境,所以,No.
大致 html 如下:
const list = [1,2,3,4,5]
render: function (createElement) {
return createElement(
'ul', {
attrs: {
id: 'list',
},
style: {
'fontSize': '24px'
},
'on': {
click: this.handler
}
}, [
list.map((item) => {
return createElement('li', {
}, [createElement('span', item)])
})
]
)
}
function eventDelegate (parentSelector, targetSelector, events, foo) {
// 触发执行的函数
function triFunction (e) {
// 兼容性处理
var event = e || window.event;
// 获取到目标阶段指向的元素
var target = event.target || event.srcElement;
// 获取到代理事件的函数
var currentTarget = event.currentTarget;
// 处理 matches 的兼容性
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function (s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
}
// 遍历外层并且匹配
while (target !== currentTarget) {
// 判断是否匹配到我们所需要的元素上
if (target.matches(targetSelector)) {
var sTarget = target;
// 执行绑定的函数,注意 this
foo.call(sTarget, Array.prototype.slice.call(arguments))
}
target = target.parentNode;
}
}
// 如果有多个事件的话需要全部一一绑定事件
events.split('.').forEach(function (evt) {
// 多个父层元素的话也需要一一绑定
Array.prototype.slice.call(document.querySelectorAll(parentSelector)).forEach(function ($p) {
$p.addEventListener(evt, triFunction)
})
})
}
eventDelegate('#list', 'li', 'click', function () { console.log(this) })
结果如下:
event delegation.png
网友评论