DOM 事件
DOM使JavaScript有能力对HTML上的事件做出反应。包括鼠标或键盘的点击事件,移动事件以及页面中内容的变化。HTML元素事件是浏览器内在自动产生的,当有事件发生时html元素会向外界发出各种事件。
DOM事件模型
- 让我们先从一个例子入手
<div class=爷爷>
<div class=爸爸>
<div class=儿子>
文字
</div>
</div>
</div>
当我们点击这个文字时,算不算点击了儿子呢,那么爸爸与爷爷呢,如果分别给这三个div做事件监听,那么先从谁开始呢。这个具有争议的话题,不同的浏览器有不同的看法,IE认为应该按照儿子->爸爸->爷爷 的顺序,但是当时的网景却认为应该按照爷爷->爸爸->儿子的顺序来执行,最后W3C出场了,他发布了标准规定浏览器应该同时支持两种调用顺序。先按照爷爷->爸爸->儿子的顺序来看有没有函数监听需要调用,然后再儿子->爸爸->爷爷的顺序来看看有没有函数监听需要调用。那岂不是一个函数需要调用两次了,并不,开发者可以自己决定到底使用哪种顺序。
事件捕获:从外向内找监听函数叫做事件监听
事件冒泡:从内向外找监听函数叫做事件冒泡
DOM事件模型分为两类,一种是IE所使用的冒泡模型事件,另一类就是w3c所制定的标准定义的冒泡型与捕获型

addEventListener``removeEventListen
两个函数.至于IE5使用的是attachEvent
例如:爸爸.addEventListener('click',fn,false)
爸爸.addEventListener*('click',fn)
.第一个参数是事件类项,第二个参数是处理函数,而第三个参数不传或是false就让fn走冒泡阶段。如果第三个参数传true就意为着在捕获阶段就处理函数。

target和current.Target
,例如<div><span>文字</span></div>
当对div做事件监听时,当点击文字时,那么target指的是span标签,而currentTarget指的是div标签,前者指的是用户操作的元素而后者指的是用户监听的元素。
捕获阶段不可以中断,但是冒泡阶段确是可以中断,使用e.stopPropagation
可以阻止冒泡,凡事都有例外,有些事件也不可以阻止冒泡,具体可以查看具体事件的MDN文档,Bubbles事件是否以冒泡,cancelable 开发者是否可以取消冒泡。
自定义事件
目前浏览器自带事件有很多,那么我们是否也可以自定义一个事件呢,答案当然是可以的了。[自定义一个事件](js.jirengu.com/tuhonowiga/…
事件委托
js里的事件委托:当事件触发时,把想要做的事情委托给父元素处理。抽象的东西当然是要有一个例子来说明就更加形象化了。



setTimeout(()=>{
let button=document.createElement('button')
button.textContent='26'
div1.appendChild(button)
},1000)
let buttonList=document.getElementsByTagName("button")
for(let i=0;i<buttonList.length;i++){
buttonList[i].addEventListener("click",()=>{
console.log('button被点击了')
}
)
}
let div1=document.getElementsByTagName('div')[0]
很遗憾是没有任何效果的,所以只有监听祖先,等点击的时候再看是不是需要监听的元素即可. 既然事件委托这么有用,那么封装一个事件委托就显得极其重要了,下面函数可以参考
有问题的
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)
}
})
}
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 t = e.target
while (!t.matches(selector)) {
if (element === t) {
t = null
break
}
console.log(t)
t = t.parentNode
console.log(t)
}
t && fn.call(t, e, t)
})
return element
}
on('click', '#div1', 'button', () => {
console.log('button被点击了')
})