给ul下面多个li绑定监听事件
这是一个非常常见的面试题
方法1
给ul下面每一个li标签都绑定点击事件。
var itemli = document.getElementsByTagName("li");
for(var i = 0; i<itemli.length; i++){
itemli[i].index = i; //给每个li定义一个属性索引值
itemli[i].onclick = function(){
alert(this.index+this.innerHTML);
}
}
方法2(JS事件代理)
从方法1中可以看出,当逐个给每个li绑定监听事件,当li太多之后,需要绑定很多监听器,(未清除监听事件)可能会导致内存泄漏,也让代码变得复杂;并且频繁的操作DOM是非常消耗性能的,如果有1000个li,怎么办呢?我们还有另一种思路,事件代理,又称事件委托。
简单的来讲就是利用JS中事件的冒泡属性,把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。
所以我们可以只给ul标签绑定监听事件,点击li会通过冒泡触发ul的click事件,然后也可以实现。
var ul = document.querySelector("ul");
ulItem.onclick = function (e) {
e = e || window.event; //这一行及下一行是为兼容IE8及以下版本
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() === "li") {
var li = this.querySelectorAll("li");
index = Array.prototype.indexOf.call(li, target);
alert(target.innerHTML + index);
}
}
实际使用场景示例:
import React from 'react'; import { useEffect } from 'react';
import './css/index.css';
function App() {
const list = [
{ id: "10002", name: 'book1' },
{ id: "10003", name: 'book2' },
{ id: "10004", name: 'book3' }
]
function liClickHandle(event) {
event = event || window.event;
var target = event.target || event.srcElement;
console.log(target.id);
switch (target.id) {
case "10002":
console.log(target)
break;
case "10003":
console.log(target)
break;
case "10004":
console.log(target)
break;
default:
console.log("error")
}
}
useEffect(() => {
var ul = document.getElementById("ulid");
ul.addEventListener('click', liClickHandle, false);
return () => {
ul.removeEventListener('click', liClickHandle, false);
};
}, [])
return (
<div className="App">
<ul id="ulid">
{
list.map((item, index) => {
return (<li id={item.id} key={item.id}>{item.name}</li>)
})
}
</ul>
</div>
);
}
export default App;
监听事件:
addEventListener(event, function, useCapture);
第一个参数是事件的类型(比如 "click" 或 "mousedown")。 第二个参数是当事件发生时我们需要调用的函数。 第三个参数是布尔值,指定使用事件冒泡还是事件捕获。此参数是可选的。 useCapture默认值是 false,将使用冒泡传播,如果该值设置为 true,则事件使用捕获传播。
在 HTML DOM 中有两种事件传播的方法:冒泡和捕获。
事件传播是一种定义当发生事件时元素次序的方法。假如
元素内有一个
,然后用户点击了这个
元素,应该首先处理哪个元素“click”事件?
在冒泡中,最内侧元素的事件会首先被处理,然后是更外侧的:首先处理
元素的点击事件,然后是
元素的点击事件。
在捕获中,最外侧元素的事件会首先被处理,然后是更内侧的:首先处理
元素的点击事件,然后是
元素的点击事件。