> 文章列表 > DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)

DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)

DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)

1. 事件绑定方式

1. 直接给元素添加事件属性

<input  onclick="alert('我被点击了!')"  type="button"  value="点我试试" />

优点:大家都会,几乎所有的浏览器都支持

缺点:夹杂在HTML代码中,代码不简洁;这种事件写法效率不高;不符合“行为,样式,结构”相分离。

2. js中赋值事件

<button id="btn">点我</button>
<script>var btn = document.getElementById("btn");btn.onclick = function() {console.log("事件触发")}// 事件解绑
btn.onclick = null
</script>

优点:符合“行为,样式,结构”相分离;便于操作当事对象;方便读取事件对象

缺点: 只能给一个元素注册一个相同事件,绑定多个相同事件,后一个会覆盖前一个

  var btn = document.getElementById("btn");btn.onclick = function() {console.log("事件触发1")}btn.onclick = function() {console.log("事件触发2")}
// 事件触发1

3. 事件监听 addEventListener()

<button id="btn">点我</button>
<script>var btn = document.getElementById("btn");btn.addEventListener("click", function () { console.log("事件触发");});// 事件解绑
btn.removeEventListener("click", function () { console.log("事件解绑触发");
})
</script>

addEventListener第三个参数,Boolean类型值,可指定事件冒泡阶段还是捕获阶段触发,true-捕获,false-冒泡,默认false,既冒泡。

优点:可以注册多个相同时间,后面的事件不会被覆盖

<button id="btn">点我</button>
<script>var btn = document.getElementById("btn");btn.addEventListener("click", function () { console.log("事件触发1");});btn.addEventListener("click", function () { console.log("事件触发2");});
</script>
// 事件触发1
// 事件触发2

缺点: 写法相对复杂

2. DOM事件流

DOM事件流(event flow )存在三个阶段:

  1. 事件捕获阶段
  2. 处于目标阶段
  3. 事件冒泡阶段。
    DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)
事件捕获(*由外到内):

通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。

事件冒泡(有内到外):

与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。

dom标准事件流的触发的先后顺序为:先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。不同的浏览器对此有着不同的实现,IE10及以下不支持捕获型事件,所以就少了一个事件捕获阶段,IE11、Chrome 、Firefox、Safari等浏览器则同时存在。

实践:

<body>
<div id="box1"><span>box1</span><div id="box2"><span>box2</span><div id="box3"><span>box3</span></div></div>
</div><script>var box1 = document.getElementById("box1");var box2 = document.getElementById("box2");var box3 = document.getElementById("box3");//给每个元素添加点击事件box1.onclick = function () {console.log("事件冒泡——box1");};box2.onclick = function () {console.log("事件冒泡——box2");};box3.onclick = function () {console.log("事件冒泡——box3");};box1.addEventListener("click", function () {console.log("事件捕获——box1");}, true);box2.addEventListener("click", function () {console.log("事件捕获——box2");}, true);box3.addEventListener("click", function () {console.log("事件捕获——box3");}, true);</script>
</body>

当点击 box3 的后,会先由外到内开始进行捕获阶段,然后有内到外开始冒泡阶段
DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)

取消事件捕获、事件冒泡

 	var box1 = document.getElementById("box1");var box2 = document.getElementById("box2");var box3 = document.getElementById("box3");//给每个元素添加点击事件box1.onclick = function () {e.stopPropagation();console.log("事件冒泡——box1");};box2.onclick = function () {e.stopPropagation();console.log("事件冒泡——box2");};box3.onclick = function () {e.stopPropagation();console.log("事件冒泡——box3");};box1.addEventListener("click", function () {e.stopPropagation();console.log("事件捕获——box1");}, true);box2.addEventListener("click", function () {e.stopPropagation();console.log("事件捕获——box2");}, true);box3.addEventListener("click", function () {e.stopPropagation();console.log("事件捕获——box3");}, true);

stopPropagation与stopImmediatePropagation区别:

1. stopPropagation:

阻止事件像外冒泡

<div id="root"><div id="box"></div>
</div>
<script>var root = document.getElementById("root");var box = document.getElementById("box");box.addEventListener("click", function (event) { event.stopPropagation();console.log("box-事件触发1");});box.addEventListener("click", function () { console.log("box-事件触发2");});root.addEventListener("click", function () { console.log("root-事件触发");});
</script>
// box-事件触发1
// box-事件触发2
2. stopImmediatePropagation:

阻止后面相同元素事件触发

<div id="root"><div id="box"></div>
</div>
<script>var root = document.getElementById("root");var box = document.getElementById("box");box.addEventListener("click", function (event) { event.stopImmediatePropagation();console.log("box-事件触发1");});box.addEventListener("click", function () { console.log("box-事件触发2");});root.addEventListener("click", function () { console.log("root-事件触发");});
</script>
// box-事件触发1
// root-事件触发

事件冒泡的作用——事件委托

<body>
<div id="box"><p class="hehe">我是文本内容</p><p class="hehe">我是文本内容</p><p>我是文本内容</p><span>我是span的内容</span>
</div><script>//事件委托//我们需要根据冒泡的元素不同,进行筛选,只有p标签才能够执行事件//第一步添加box的事件box.onclick = function (e) {e.stopPropagation()//需要获取,当前这个事件是由哪一个子元素触发的//第二步 兼容事件对象evar e = e || window.event;//第三步 兼容取出触发事件的元素的方式  target srcElementvar tar = e.target || e.srcElement;//第四步 检测tar是什么标签
//        if (tar.nodeName.toLowerCase() == "p") {if (tar.nodeName.toUpperCase() == "P") {console.log("呵呵,我是p的代码");}};//可以通过nodeName属性获取到元素的标签名console.log(box.nodeName);
</script>
</body>