前端⾯试js-⼿写事件委托(⼀点⼩改进)最近刚好在学js的事件机制,写这个是看到提到了⼀个腾讯的⾯试题。我先把⽂章的代码稍作改动贴在这⾥。
<body>
<div id="outer" >
<div id='middle'>
<div id="inner"></div>
</div>
</div>
<script>
function delegateEvent(interfaceEle, selector, type, fn) {
if(interfaceEle.addEventListener) {
interfaceEle.addEventListener(type, eventfn, false);
} else {
interfaceEle.attachEvent("on" + type, eventfn);
}
function eventfn(e) {
var e = e || window.event;
var target = e.target || e.srcElement;
if(matchSelector(target, selector)) {
if(fn) {
fn.call(target, e);
}
}
}
}
function matchSelector(ele, selector) {
// if use id
if(selector.charAt(0) === "#") {
return ele.id === selector.slice(1);
}
// if use class
if(selector.charAt(0) === ".") {
return(" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
}
/
/ if use tagName
return LowerCase() === LowerCase();
}
//调⽤
var outer = ElementById("outer");
var middle = ElementById("middle");
delegateEvent(outer, "#middle", "click", function() {
console.log('test');
})
</script>
</body>
作者:⼀只dororo
链接:www.jianshu/p/7ea01a3beb7a
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
显⽰效果如图:
但是这段代码有⼀个⼩问题:⽤⿏标点击绿⾊⽅块,不会输出‘test’,这仿佛违背了我们希望事件冒泡的初衷。
这是由于在绑定的时候,很关键的⼀个地⽅在eventfn函数,它限制了只有当target就是selector匹配的元素时,才会调⽤handler。⽽事实上我们在调⽤这个函数的时候,target是selector匹配到的元素的⼦节点也可以。
在这⾥介绍⼀个新的api,,他返回⼀个布尔值,判断node是不是parent节点的后代或parent本⾝。
因此我们修改代码为:
function delegateEvent(interfaceEle, selector, type, fn) {
if(interfaceEle.addEventListener) {
interfaceEle.addEventListener(type, eventfn, false);
} else {
interfaceEle.attachEvent("on" + type, eventfn);
}
function eventfn(e) {
var $selector = document.querySelector(selector);
var e = e || window.event;
var target = e.target || e.srcElement;
if(contain($selector, target)) {
if(fn) {
fn.call(target, e);
}
}
}
}
function contain(parent, node) {
if (ains) {
ains(node)
} else { //兼容不⽀持contains⽅法的浏览器
while (node) {
if (node === parentNode) {
return true;
} else {
node = node.parentNode;
}
}
return false;nodeselector
}
}
现在再点击绿⾊⽅块也可以打印'test'啦。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论