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。