事件委托类
题目:
2、使用原生js,ul li中的最后一个p标签。 (1) 删除最后一个p标签
(2) 点击任意li标签,打印所在序号。(用直接绑定 和 事件委托) 2种方式
答案:
<ul id="oBox">
<li>
<p>1</p>
<p>2</p>
</li>
<li>
<p>1</p>
<p>2</p>
</li>
<li>
<p>1</p>
<p>2</p>
</li>
</ul>
<script>
let oUl = document.getElementById('oBox');
let oLi = oUl.getElementsByTagName('li');
// 移除最后一个p节点
for(let i = 0; i < oLi.length; i ++) {
var lastChild = oLi[i].lastElementChild ? oLi[i].lastElementChild : oLi[i].lastChild;
oLi[i].removeChild(lastChild)
}
// 直接绑定
for(let i = 0;i < oLi.length; i ++) {
oLi[i].onclick = function() {
alert(i)
}
}
// 事件委托
oUl.addEventListener("click",clickHandler);
function clickHandler(e) {
if(e.target.nodeName.toLowerCase() !== 'li') return; // 或者写 if(e.target.constructor!==HTMLLIElement) return;
let arr = Array.from(oUl.children)
let index = arr.indexOf(e.target);
alert(index)
}
</script>
优化
如果用户点击的是 li里面的 span,就没法触发 fn,这显然不对。 那下面我们来看一下正确的事件委托应该怎么写:
function delegate(element, eventType, selector, fn) {
element.addEventListener(eventType, e => {
let el = e.target
while (!el.matches(selector)) {
if (element === el) {
el = null
break
}
el = el.parentNode
}
el && fn.call(el, e, el)
})
return element
}