dom的事件委托
- 如果我们有很多元素以类似的方式处理,那么我们不是为每个元素分配一个处理程序 - 我们将一个处理程序放在它们的共同祖先上。这是事件委托
- 优点:可以减少内存占用,减少事件注册
<ul class=list>
<li></li>
<li></li>
<li></li>
...
<li>n</li>
</ul
- 可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
- 怎么阻止默认动作?
e.preventDefault();
e.returnValue;
$form.on('submit',(e)=>{
//阻止默认事件
// e.preventDefault();//适合普通游览器 如阻止链接跳转和表单提交
//e.returnValue;//适用于ie6,7,8
return false;//无兼容
)};
- 怎么阻止事件冒泡?
标准写法:利用事件对象里的stopPropagation()方法
非标准写法(IE6-8)利用事件对象cancelBubble属性
document.getElementById('box1').onclick= function(e){
var ev = e || window.event
//阻止冒泡
//ev.stopPropagation()
ev.cancelBubble = true;
this.style.backgroundColor = 'pink'
}
target和currentTarget
//当用户点击文字的时候
<div> //e.currentTarget 就是div
<span>文字</span> //e.target就是span
</div>
e.target: 用户操作的元素
e.currentTarget: 程序员监听的元素
this为e.currentTarget, 是不推荐的用法,因为this指向不确定
- 实际开发过程中可能会遇到以下两种情形:
- 为了满足同时监听多个元素。
- 需要监听的元素还不存在
此时,可以对这些元素的祖先进行监听,这样就可以节省内存和动态的监听元素
- 示例1
- 要给100个按钮添加点击事件,我们先监听这100个按钮的祖先,等冒泡的时候判断target是不是这100按钮的其中一个。 饥人谷JS Bin (jirengu.com)
div1.addEventListener('click',(e)=>{
const t = e.target
if(t.tagName.toLowerCase() === 'button'){
console.log('button 被点击了!')
}
})
- 当需要操作的元素一开始不存在时,无法写在js中对该元素进行监听,通过事件委托一样可以实现。代码如下 饥人谷JS Bin (jirengu.com)
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 被点击了!')
}
})
- 这样做的优点是
- 省内存
- 可以监听动态元素
封装事件委托
setTimeout(() =>{
const button = document.createElement('button')
button.textContent = 'click 1'
div1.appendChild(button)
},1000)
on('click', '#div1', 'button', ()=>{
console.log('我被点击了')
})
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)
}
})
}