DOM事件包括100多种,包括点击事件等。这些事件能够事件捕获和事件冒泡,事件捕获的特色是从外到内监听函数,即从父亲到儿子;事件冒泡的特色是从内到外监听函数,即从儿子到父亲。程序员能够决定使用事件捕获仍是事件冒泡。程序员
捕获事件web
元素.addEventListener('click',fn,不传参或者falsy)
复制代码
冒泡事件浏览器
元素.addEventListener('click',fn,true)
复制代码
CSS:给class属性以level开头的每个div元素bash
div[class^=level]{
//添加CSS属性
}
复制代码
level1.addEventListener('click',(e)=>{
//将传入对象e暂存
const t=e.currentTarget
setTimeout(()=>{
//点击时去掉自身的.x
t.classList.remove('x')
},n*1000)
n+=1
},true)
复制代码
函数的结构:fn里面有3个函数,第一个是将参数e暂存,为何须要暂存:由于e只存在点击的一瞬间,执行setTimeout里面时,e已经消失,不会执行;第二个参数是1秒后再执行;第三个是将n加1,不至于全部的闹钟一块儿响app
level1.addEventListener('click',(e)=>{
//将参数e暂存
const t=e.currentTarget
setTimeout(()=>{
//点击时将自身的.x去掉
t.classList.remove('x')
},n*1000)
n+=1
},true)
level1.addEventListener('click',(e)=>{
//将参数e暂存
const t=e.currentTarget
setTimeout(()=>{
//点击时将自身的.x去掉
t.classList.add('x')
},n*1000)
n+=1
},false)
复制代码
<div>
<span>文字</span>
</div>
复制代码
当用户点击了文字,e.target就是span,e.currentTarget就是div
复制代码
W3C的事件模型:先捕获(先爸爸后儿子),再冒泡(先儿子再爸爸)。注意,e对象传给全部监听函数,监听事件结束后,能够认为e对象不存在。函数
当用户操做的元素就是开发者监听的元素,fn分别在捕获阶段和冒泡阶段监听click事件ui
div.addEventListener('click',f1) //捕获事件
div.addEventListener('click',f2,true) //冒泡事件
复制代码
请问,先执行哪一个事件? 谁先监听,就先执行哪一个this
捕获事件不能取消,可是冒泡能够取消。e.stopPropagation()能够中断冒泡,浏览器再也不往上走,通常用于封装某些独立的组件,Bubbles属性是该事件是否冒泡,Cancelable的属性是开发者是否能够取消冒泡spa
<div id="x">
………………
</div>
复制代码
第一:阻止滚轮滚动code
x.addEventListener("wheel",
(e)=>{
e.preventDefault()
}
)
复制代码
第二:阻止鼠标滚动,设置CSS
::-webkit-scrollbar{
width:0 !improtant
}
复制代码
第三:阻止手机的触屏滚动
x.addEventListener('touchstart',
(e)=>{
e.preventDefault()
}
)
复制代码
HTML:
<div id="div1">
<button id="button1">
点击触发frank事件
</button>
</div>
复制代码
JavaScript:
button1.addEventListener('click',()=>{
//声明自定义事件
const event = new CustomEvent('frank',{
//自定义事件的信息
detail:{name:'frank',age:18},
//能够冒泡
bubbles:true,
//不能阻止冒泡
cancelable:false
})
//让button1触发事件,至关于调用
button1.dispatchEvent(event)
}))
//监听button1
button1.addEventListener('frank',(e)=>{
console.log(e.detail)
})
复制代码
<div id="div1">
…………中间有100个button标签
</div>
复制代码
请问,若是给100个button标签添加点击事件,怎么作?
思路:监听它们的祖先元素div,等冒泡的时候判断target是否是这100个按钮中的一个。
作法:
div1.addEventListener('click',(e)=>{
const t=e.target
if(t.tagName.toLowerCase()=== 'button'){
console.log('button 被点击了')
console.log('button内容是'+t.textContent)
}
})
复制代码
体现出事件委托的优势:省监听数(省内存)
若是监听目前不存在的元素的点击事件,怎么作?
思路:监听祖先元素,等点击的时候看看是否是我想要监听的元素。
作法:
//1秒钟以后,在div里面建立button
setTimeout(()=>{
//建立button按钮
const button=document.createElement('button')
//button按钮里面文本
button.textContent='click 1'
//向div1里面添加子节点button
div1.appendChild(button)
},1000)
//监听button元素1秒钟以后是否被用户点击
div1.addEventListener('click',(e)=>{
//获取用户操做的元素
const t=e.target
if(t.tagName.toLowerCase() === 'button'){
console.log('button 被click')
}
})
复制代码
体现出事件委托的优势:能够动态监听元素
用户只须要经过on事件,监听div下面的button是否被点击
on('click','#div1','button',()=>{
console.log('button被点击了')
})
function on(eventType,element,selector,fn){
//若是element不是一个元素,就获取element所在的元素
if(!(element instanceof Element)){
element=document.querySelector(element)
}
element.addEventListener(eventType,(e)=>{
const t=e.target
//matches判断一个元素是否知足一个选择器
if(t.matches(selector)){
fn(e)
}
})
}
复制代码
上面的事件委托是DOM事件,DOM是由浏览器提供的,JS只是调用了DOM提供的addEventListener。