简单版
document.getElementById("app").innerHTML = `
<ul>
<li> <img/> </li>
<li> <img/> </li>
<li> <img/> </li>
<li> <img/> </li>
<li> <img/> </li>
</ul>`
ul.addEventListener('click', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
fn() // 执行某个函数
}
})
如果点击的是<li>里面的<img/>标签, 上面的写法就无效了 ↑
改进版 ↓
document.getElementById("app").innerHTML = `
<ul id="content">
<h1>事件委托</h1>
<li class="item" id="1"><span>aaa</span></li>
<li class="item" id="2"><span>bbb</span></li>
<li class="item" id="3"><span>ccc</span></li>
</ul>
`;
const content = document.getElementById("content");
delegate(content, "li", "click", (e, target) => {
console.log(e, target);
});
/**
* 有可能点击了<span/> or <h1/> or <ul/>,这样就获取不到id了
* @param {dom对象} ul
* @param {字符串 如: 'li'} li
* @param {字符串 如: 'onclick'} eventType
* @param {Function} callback
*/
function delegate(ul, li, eventType, callback) {
content.addEventListener(eventType, (e) => {
const target = findLi(ul, li, e.target);
target && callback.call(target, e, target);
});
}
/**
* @param {dom对象} ul
* @param {字符串 如: 'li'} li
* @param {dom对象} target
*/
function findLi(ul, li, target) {
if (target === ul) return null;// 没找到
if (target.matches(li)) return target;// 找到了
return findLi(ul, li, target.parentNode);
}