事件委托
事件委托:通俗地来讲,就是把一个元素响应事件(click、keydown......)的函数委托到另一个元素
这里引用一下别人的话:
一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。
一、省监听数(内存)
如果要给100个按钮添加点击事件,我们只需要用事件委托监听这100个按钮的祖先,等冒泡的时候判断target是不是这100个按钮中的一个
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="div1">
<button data-id="1">click 1</button>
<button>click 2</button>
<button>click 3</button>
//...此处省略96行
<button>click 100</button>
</div>
</body>
</html>
div1.addEventListener('click',(e)=>{
const t=e.target
if(t.tagName.toLowerCase()==='button'){ //判断被操作的元素是否为button
console.log('button被点击了+t.textContent')
console.log('button data-id是' + t.dataset.id) //dataset.id用来获取data-id的值
}
})
二、可监听动态元素
如果有一个button在一秒钟之后出现,那我们监听改元素的祖先,等点击的时候看看是不是我想要监听的元素即可
setTimeout(() => {
const button = document.createElement('button')
button.textContent = 'click 1'
div1.appendChild(button)
}, 1000)
div1.addEventListener('click', (e) => {
const t = e.target
if (t.tagName.toLowerCase() === 'button') {
console.log('button 被click')
}
})
封装事件委托
思考:
写出这样一个函数on('click','#testDiv','li',fn),当用户点击#testDiv里的li元素时,调用fn函数,要求用到事件委托。
答案一(常规)
setTimeout(() => {
const button = document.createElement('button')
button.textContent = 'click 1'
div1.appendChild(button)
}, 1000)
//在div1上做事件委托看button有没有被点击
on('click', '#div1', 'button', () => {
console.log('button 被点击了')
})
//输入(事件类型,元素,选择器/准备匹配什么元素,回调函数)
function on(eventType, element, selector, fn) {
if (!(element instanceof Element)) {
element = document.querySelector(element)
}
element.addEventListener(eventType, (e) => {
const t = e.target
//判断一个元素是否满足一个选择器
if (t.matches(selector)) {
fn(e)
}
})
}
答案二(特殊)
如果button里面还有个span,span的内容是chick 1,点击chick 1 实际操作的元素是span,就不能通过button被点击了。
要用递归判断,如果当前元素不匹配button,就向自己的祖辈寻找,如果祖辈里有button就说明点击了button。
setTimeout(() => {
const button = document.createElement('button')
const span = document.createElement('span')
span.textContent = 'click 1'
button.appendChild(span)
div1.appendChild(button)
}, 1000)
//在div1上做事件委托看button有没有被点击
on('click', '#div1', 'button', () => {
console.log('button 被点击了')
})
//输入(事件类型,元素,选择器/准备匹配什么元素,回调函数)
function on(eventType, element, selector, fn) {
if (!(element instanceof Element)) {
element = document.querySelector(element)
}
element.addEventListener(eventType, e => {
let el = e.target
//看看被操作的元素是否符合button
while (!el.matches(selector)) {
//如果在找的时候一直找到了div1,就认为找不到了,判定为空,跳出
if (element === el) {
el = null
break
}
//不符合就让这个元素等于父元素
el = el.parentNode
}
//如果找到了就调用fn,第一个参数传e,第二个传匹配到的元素
el && fn.call(el, e, el)
})
return element
}
-------以上 代码引用自语雀---釉纸糖
网友评论