# 事件
事件就是用户或者浏览器进行的特定行为,比如:鼠标点击事件。
# 事件名称
比如:click就是一个事件名。
# 事件流的执行过程
事件流:指的是 DOM 事件流(多个事件按照一定顺序执行),DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。 事件流的执行过程:从window开始,最后回到window。 事件流被分为三个阶段:事件捕获(1-5),事件触发(5-6),事件冒泡(6-10)。
来自网上的图片:

# 事件冒泡
来自百度的解释:
当事件发生后,这个事件就要开始传播(从里到外或者从外向里)。为什么要传播呢?因为事件源本身(可能)并没有处理事件的能力,即处理事件的函数(方法)并未绑定在该事件源上。
就比如:我们用button产生一个click事件,但是由于button按钮本身可能不能处理这个事件,就要开始传播出去这个事件。 实现事件冒泡的条件是:元素之间有嵌套,每个元素都有相同的事件,这样当最里层的事件触发时,这个事件就会一级一级向上传播,也就是”冒泡“。
举个例子:在一个div里面嵌套另一个div,两个div都绑定了相同的事件监听函数click。这样,当里层点击事件触发时,外层的点击事件也会被触发。
<div id="outer">
 <div id="inner">
 </div>
</div>
<script>
 window.onload = function () {
   let inner = document.getElementById('inner')
   let outer = document.getElementById('outer')
   inner.addEventListener('click', function (e) {
     console.log('inner');
   })
   outer.addEventListener('click', function () { 
     console.log('outer');
   })
 }
</script>
结果为:

# 阻止事件冒泡
- 一般浏览器:event.stopPropagation()
- IE浏览器:event.cancelBubble = true
# 阻止默认事件
- 一般浏览器:event.preventDefault()
- IE浏览器:event.returnValue = false
# addEventListener的第三个参数
addEventListener方法用于将事件和函数进行绑定,函数为:addEventListener(event, fn, useCapture),这些参数分别是:事件名,事件处理函数,第三个参数 useCapture 是一个布尔值,用来设置该事件的执行是在哪个阶段发生的(默认是在冒泡阶段)。
- true:表示该事件是在“事件捕获阶段”触发的。(由外向内)
- false:表示该事件是在“事件冒泡阶段”触发的。(由内向外)
举个例子:在一个div里面嵌套另一个div,两个div都绑定了相同的事件监听函数click。
将第三个参数设置为true,事件在 捕获阶段 执行:
<div id="outer">
 <div id="inner">
 </div>
</div>
<script>
 window.onload = function () {
 let inner = document.getElementById('inner')
 let outer = document.getElementById('outer')
 inner.addEventListener('click', function (e) {
 console.log('inner');
 }, true)
 outer.addEventListener('click', function () { 
 console.log('outer');
 }, true)
 }
</script>
由于是 捕获阶段 执行,即:由外向内执行,所以结果为: outer inner。
结果为:

将第三个参数设置为false,事件在 冒泡阶段 执行,输出结果为: inner outer。

# 事件处理函数/事件监听函数
事件触发后的处理函数。如:btn.onclick = fn,fn就是事件处理函数/事件监听函数。
# HTML事件处理程序
例如:
<button onclick = "fn()">click</button>
这种方式的缺点是:结构和行为耦合在一起。
# DOM0级事件处理程序
形式为:ele.on + ‘事件名称’ = 事件处理函数 例如: ele.onclick = function() {…},this指向当前元素。
# DOM2级事件处理程序
这种方式主要是通过这两个方法:addEventListener(),removeEventListener() 这种方式的优点就是:可以同一个事件处理程序绑定多个事件处理函数。
# 事件委托
事件委托要处理的问题是:解决事件处理程序过多的问题。简单来说,就是将很多个事件处理程序委托给一个事件处理程序,通过这个事件处理程序来管理这么多个事件处理程序。 好处:减少对DOM的访问,提高性能;可以对后来添加进来的元素也能绑定委托事件。
例如:在一个 ul 标签中有很多个 li 标签,我们的需求而是点击每一个 li 标签显示每一个 li 标签的内容。 如果没有使用事件委托,我们需要给每一个 li 标签都添加事件监听函数,很明显,这样的效率并不高,而且对整个网页的性能也会影响;如果我们使用事件委托,将这些 li 的事件委托给 ul 标签,这样就可以只用一个事件监听函数实现。
代码如下:
<ul id="list"> 
 <li>111111</li>
 <li>222222</li>
 <li>333333</li>
 <li>444444</li>
</ul>
<script>
 window.onload = function () { 
 // 传统的方法
 // let lis = document.getElementsByTagName('li')
 // console.log(lis);
 // for(let i = 0; i < lis.length; i++){
 //     lis[i].addEventListener('click', function () { 
 //         console.log(this.innerHTML);
 //     })
 // }
 // 使用事件委托
 let list = document.getElementById('list')
 list.addEventListener('click', function (e) { 
   let target = e.target
   console.log(target.innerHTML);
 }, false)
 }
</script>
事件委托一般使用的是 事件冒泡阶段 进行(虽然事件捕获阶段也可以),因为事件冒泡的事件流模型被所有的主流浏览器兼容,事件冒泡的兼容性更好。