本篇文章主要来讲讲 事件的冒泡机制 和 添加事件的几种方法。


一. JS的事件传递顺序: 捕获阶段 -> 目标阶段 -> 冒泡阶段

  • 捕获阶段是指从父层往子层找。比如 <body><div></div></body> ,我们会先找到 body,然后下一个才是 div。就像中央领导发布政策一样。 从上往下通知。

  • 目标阶段就是找到目标的那段时间,这个我们暂且不谈。

  • 冒泡阶段就是从子层往外层传。比如 <body><div></div></body> ,这个时候是先写 div ,再找 body。往外依次冒泡。从内往外通知。

    先从外到内传一圈波纹,再从内到外传一圈波纹

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    </head>
    <body>
    <div id="div2">
    <div id="div1">
    点我
    </div>
    </div>
    </body>
    <script type="text/javascript">
    const oBtn = document.getElementById('div1')
    const div1 = document.getElementById('div1')
    const div2 = document.getElementById('div2')
    // addEventListener 的第三个参数默认为 false —— 表示该事件在冒泡阶段触发; true 则表示在捕获阶段触发
    div1.addEventListener('click', function (event) {
    console.log("A");
    }, true);
    div2.addEventListener('click', function (event) {
    console.log("B");
    });
    div1.addEventListener('click', function (event) {
    console.log("C")
    }, false);
    div2.addEventListener('click', function (event) {
    console.log("D");
    }, true);
    </script>
    </html>

答案是: DACB

根据 JS 的 dom 事件顺序 ———— “从外到内,从内到外” 和 addEventListener第三个参数所控制的触发阶段我们可以很容易地解答。

  • 1.div2 在外面,div1 在里面。捕获阶段时优先;掠过 div2 后再掠过 div1,发现他们要找的人是 D 和 A (因为第三个参数为true)
  • 2.然后到了 冒泡阶段;掠过 div1 后途经 div2;他们要找的分别是捆绑在 div1 上的 C 然后是 B。

二. 兼容性地添加 JS 事件

如果我们要给按钮添加事件,我们会怎么做呢?

也许我们会这么做<button onclick="console.log('1')">点我</button>

很明显地,它破坏了标签。我们应该让 html 和 事件分离,否则,我们下一次要修改这个按钮就不好操作了。

他有个致命的缺点:那就是只能用此方法添加一个事件,后面的会覆盖前面(原理是指向了不同的对象)。

  • 错误示范:
      const oBtn = document.getElementsByTagName('button')[0];
    oBtn.onclick = function() {
    console.log('1');
    }
    // 只会显示下面这次
    oBtn.onclick = function() {
    console.log('我是第二次');
    }
  • 正确示范:
      const oBtn = document.getElementsByTagName('button')[0];
    // addEventListener
    oBtn.addEventListener("click", () => {console.log('1')});
    oBtn.addEventListener("click", () => {console.log('我是第二次')} );
    // 上面的两次都会被认可

我们已经决定放弃(不推荐)使用 onclick;但接下来还有一件事情要做,那就是兼容性问题。

事件并不总是如我们所想的运转,感觉失望和沮丧是徒劳无益的,我们要想办法改变我们自己适应这个世界。

IE 6/7/8 上并没有 addEventListener.它们使用了特殊的 attachEvent;对于这样的少数人,我们也不能完全放弃。

代码的健壮性是锦上添花还是...至关重要的?也许这是裁定程序员优秀的标准吧。

遂改成这样。(可以在老IE和Chrome上感受一下差距)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div2" style="border: 1px solid #089e8a;padding: 10px;">
<div id="div1" style="border: 1px solid blue;padding: 10px;">
点我
</div>
</div>
</body>
<script type="text/javascript">
var oBtn = document.getElementById('div1')
var div1 = document.getElementById('div1')
var div2 = document.getElementById('div2')
// 注意:attachEvent 只有冒泡没有捕获!!!
var addEvent = function (dom, eventType, method, isBubble) {
eventType = eventType || 'click'
isBubble = isBubble || false
if (dom.addEventListener) {
dom.addEventListener(eventType, method, isBubble)
} else if (dom.attachEvent) {
dom.attachEvent('on' + eventType, method)
}
}
var methodX = function () {
console.log('methodX')
}
var method2 = function () {
console.log('method2')
}
addEvent(div1, 'click', methodX)
addEvent(div2, 'click', method2)
</script>
</html>

除此之外我们还想要知道的 addEventListener 和 attachEvent 都是讲究规则的。谁先来,谁在上面。

  // 多个 addEventListener 的执行顺序:谁先被添加,谁就在前面
div1.addEventListener('click', event => {
console.log('first')
})
div1.addEventListener('click', event => {
console.log('second')
})
div1.addEventListener('click', event => {
console.log('third')
})

complete

JS事件冒泡机制和兼容性添加事件的更多相关文章

  1. 浅谈js的事件冒泡机制

    很多人都听说过,js的事件冒泡机制,其实,这个说法还是比较生动形象的,就是一个水泡在水底下,冒泡到水面的过程. 那js的事件冒泡机制呢,就是一个DOM树,一级一级向上冒的过程,最终是到document ...

  2. 这可能是最简明扼要的 js事件冒泡机制+阻止默认事件 讲解了

    哎 js事件冒泡机制和阻止冒泡 阻止默认行为好像永远也整不清楚,记了忘 忘了记...醉了 这篇文章写完以后下次再忘记 就呼自己一巴掌,忘一次一巴掌 首先要明白两个概念——事件和事件流 事件指的是用户或 ...

  3. js的事件冒泡机制

    js的事件冒泡机制呢,就是一个DOM树,一级一级向上冒的过程,最终是到document这个根节点这里.js的事件冒泡机制,就像是一个水泡在水底下,冒泡到水面的过程. 摘自醉清玄

  4. 解析Javascript事件冒泡机制

    本资源引自: 解析Javascript事件冒泡机制 - 我的程序人生 - 博客频道 - CSDN.NET http://blog.csdn.net/luanlouis/article/details/ ...

  5. JavaScript中的事件冒泡机制

    事件冒泡机制 事件冒泡发生的条件:当为多个嵌套的元素设置了相同的事件处理程序,它们将触发事件冒泡机制.在事件冒泡中,最内部的元素将首先触发其事件,然后是栈内的下一个元素触发该事件,以此类推,直到到达最 ...

  6. 数组练习:各种数组方法的使用&&事件练习:封装兼容性添加、删除事件的函数&&星级评分系统

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. window.open('') 火狐,IE事件冒泡处理,点击事件冒泡处理

    window.open('') 火狐,IE事件冒泡处理,点击事件冒泡处理 写PC下拉菜单的时候,hover样式显示下拉菜单,可能会这样写 <li class="xb_li1" ...

  8. js事件冒泡机制

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Javascript事件冒泡机制

    1. 事件 在浏览器客户端应用平台,基本生都是以事件驱动的,即某个事件发生,然后做出相应的动作. 浏览器的事件表示的是某些事情发生的信号.事件的阐述不是本文的重点,尚未了解的朋友,可以访问W3scho ...

随机推荐

  1. dbcc练习1

    dbcc tranceon(2588,3604) dbcc ind() dbcc page()

  2. ACM学习历程—BZOJ 2115 Xor(dfs && 独立回路 && xor高斯消元)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2115 题目大意是求一条从1到n的路径,使得路径xor和最大. 可以发现想枚举1到n的所有路 ...

  3. python实现redis三种cas事务操作

    cas全称是compare and set,是一种典型的事务操作. 简单的说,事务就是为了存取数据库中同一数据时不破坏操作的隔离性和原子性,从而保证数据的一致性. 一般数据库,比如MySql是如何保证 ...

  4. bzoj 2096 [POI2004]ZAW——二进制枚举

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2069 可以把直接相连的点分成  从1点出的一部分  和  走向1点的一部分.多起点最短路就和 ...

  5. Azure xplate cli创建虚拟机

    Azure的管理工具多种多样.其中Portal和PowerShell是经常使用的. 但用MAC和Linux的同学最喜欢的还是Bash环境. Azure也提供了跨平台的命令行工具:Azure xplat ...

  6. 事务之五:Spring @Transactional工作原理

    本文将深入研究Spring的事务管理.主要介绍@Transactional在底层是如何工作的. JPA(Java Persistence API--java持久层)和事务管理 很重要的一点是JPA本身 ...

  7. leetcode-002

    给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字.将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. 示例: 输入:(2 -& ...

  8. ubuntu下sourceinsight的安装

    转载自blog.csdn.net/zzobin/article/details/7376616 1. 安装wine 详看:http://wiki.ubuntu.org.cn/Wine sudo apt ...

  9. 项目中gulp使用发生的错误及解决

    在项目开发中,执行gulp css来生成合成的css文件时,报如下错误 Error: Cannot find module 'browserslist' 解决方法: npm install brows ...

  10. HTML5新api即pushState和replaceState实现无刷新修改url

    1,首先我面临一个需求,页面回退时需要知道来之前的页面状态.很简单,回退时在url里赋参数即可.问题是在ipad上,回退按钮是安卓那边的,我控制不了.只好采用js无刷新修改url历史记录,来告诉服务器 ...