原文地址:https://www.jianshu.com/p/dc1520327022

Js事件分发与DOM事件流

对JavaScript分发事件不熟悉,网上查阅相关资料整理后,记录一下对Javascript事件分发机制相关的知识。
当触发某个事件时会相应生成一个事件对象,而这个事件对象则会根据DOM事件流的方向进传递,看下图:

图为通过DOM事件流在DOM树传递事件的示意

图片来源:http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
事件对象会随着DOM事件流从Window依次向下,最终传递给事件目标。但是在这个过程开始之前,事件对象的传递路径需要先被确定下来。
这个传递路径是一个有序的列表,里面包含了传递到事件目标需要经过的节点。而传递路径反映了文档的树结构。列表里面的最后一项就是事件目标,列表里面先于它的项指向目标的祖先节点,它的上一项指向目标的父节点。
比如上图由Window->Document->html->body->table->tr->td。一旦传递路径被确定了,事件对象就可以经历一个或者多个事件阶段。通常有三个阶段:捕获阶段目标阶段冒泡阶段。某些阶段可能会被跳过,如果浏览器不支持,或者事件对象的传播被停止了。例如,如果把cancelBubble设置为true,冒泡阶段将会被跳过,或者stopPropagation()方法在传递之前就被调用的话,之后所有的阶段都会被跳过。

  • 捕获阶段:事件对象从目标的祖先节点Window开始传播直至目标。
  • 目标阶段:事件对象传递到事件目标。如果事件的type属性表明后面不会进行冒泡操作,那么事件到此就结束了。
  • 冒泡阶段:事件对象以一个相反的方向进行传递,从目标开始,到Window对象结束。
    直接上代码,写了三个嵌套的div:
<!DOCTYPE >
<html>
<head lang="en">
<title></title>
<meta charset="UTF-8">
<style type="text/css">
#parent { width: 300px; height: 300px;padding:10px;background:lightyellow;}
#child { width: 200px; height: 200px; background: lightblue; }
#grandchild { width: 100px; height: 100px; background: lightcoral; }
</style>
</head>
<body>
<div id="parent">
parent
<div id="child">
child
<div id="grandchild">
grandchild
</div>
</div>
</div> <script type="text/javascript">
window.alert = function (msg) {
console.log(msg);
};
var parent= document.getElementById('parent'),
child = document.getElementById('child'),
grandchild = document.getElementById('grandchild'); parent.addEventListener('click', function (e) {
alert('父节点冒泡')
}, false);
parent.addEventListener('click', function (e) {
alert('父节点捕获')
}, true);
child.addEventListener('click', function (e) {
alert('子节点捕获')
}, true);
child.addEventListener('click', function (e) {
alert('子节点冒泡')
}, false);
grandchild.addEventListener('click', function (e) {
alert('孙子节点冒泡')
}, false);
grandchild.addEventListener('click', function (e) {
alert('孙子节点捕获')
}, true); </script>
</body>
</html>

当点击了parent时,依次打印:父节点冒泡,父节点捕获。
当点击了child时,依次打印:父节点捕获,子节点捕获,子节点冒泡,父节点冒泡。
当点击了grandchild时,依次打印:父节点捕获,子节点捕获,孙子节点冒泡,孙子节点捕获,子节点冒泡,父节点冒泡。
由此可以得出来结论,点击了目标节点后,捕获阶段里事件会从外向目标传递;到了目标阶段,捕获和冒泡的执行顺序按照事件被定义的先后顺序执行;最后冒泡阶段,又会由目标向外进行传递。

补充说明事件中stopPropagationstopImmediatePropagation区别:
两都都可以阻止事件的进一步捕获或冒泡,但后者同时可以阻止任何事件处理程序被调用,包括目标阶段的事件。
比如修改上面代码里面子节点的目标事件:

   child.addEventListener('click', function (e) {
alert('子节点捕获')
}, true);
child.addEventListener('click', function (e) {
e.stopPropagation();
// e.stopImmediatePropagation();
alert('子节点捕获2')
}, true);
child.addEventListener('click', function (e) {
alert('子节点冒泡')
}, false);

使用stopPropagation():点击子节点,依次打印:父节点捕获,子节点捕获,子节点捕获2,子节点冒泡。
使用stopImmediatePropagation():点击子节点,依次打印:父节点捕获,子节点捕获,子节点捕获2。
两者都阻止了事件向父节点进行传播,同时使用stopImmediatePropagation()阻止了事件向目标阶段后面的事件的传播。
参考:
https://www.w3.org/TR/DOM-Level-3-Events/#event-flow

如果您在阅读过程中发现有什么问题,欢迎指正。

Js-事件分发与DOM事件流的更多相关文章

  1. [DOM Event Learning] Section 4 事件分发和DOM事件流

    [DOM Event Learning] Section 4 事件分发和DOM事件流 事件分发机制: event dispatch mechanism. 事件流(event flow)描述了事件对象在 ...

  2. Js事件分发与DOM事件流

    这一篇比较透彻:https://www.jianshu.com/p/dc1520327022 点击了目标节点后,捕获阶段里事件会从外向目标传递:到了目标阶段,捕获和冒泡的执行顺序按照事件被定义的先后顺 ...

  3. 自定义控件(视图)2期笔记10:自定义视图之View事件分发机制("瀑布流"的案例)

    1. Touch事件的传递:   图解Touch事件的传递,如下: 当我们点击子View 02内部的Button控件时候,我们就触发了Touch事件. • 这个Touch事件首先传递给了顶级父View ...

  4. js事件捕获,事件冒泡,事件委托以及DOM事件流

    一:DOM事件流: 事件流是从页面接收事件的顺序,DOM2级事件规定事件流包括三个阶段: ①事件捕获阶段:用意在于事件达到目标之前捕获它,在事件捕获阶段事件流模型:document→html→body ...

  5. DOM事件: DOM事件级别、DOM事件流、DOM事件模型、DOM事件捕获过程、自定义事件

    前端面试中只要问到事件,就肯定会有DOM事件:如果回答出来了,就会一直向下延申,其实这些东西都很简单,但我第一次被问到的时候,也是懵的: DOM事件级别: DOM0 element.onclick = ...

  6. cocos2d-x 事件分发机制 ——加速计事件监听

    加速计事件监听机制 在上一篇中介绍了cocos2d-x中的触摸事件机制,这篇来介绍下游戏中也常常常使用到的加速计事件,这些都是游戏中的常常要用到的. 移动设备上一个非常重要的输入源是设备的方向.大多数 ...

  7. cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析

    (一) Android平台下: cocos2dx 版本3.2,先导入一个android工程,然后看下AndroidManifest.xml <application android:label= ...

  8. cocos2d-x 事件分发机制 ——触摸事件监听

    cocos2d-x 3.0 出来已经好久了,也已经用3.0写了几个小游戏,感觉3.0的事件触发机制太赞了,随这里总结一下.也算是对知识的一种回顾和加深理解. 3.0的事件分发机制中.须要也只须要通过创 ...

  9. js和jquery的DOM事件大全

随机推荐

  1. thinkphp概述2

    thinkphp概述,thinkphp项目构建流程,thinkphp项目结构,thinkphp配置,thinkphp控制器,thinkphp模型,thinkphp视图,thinkphp的内置模板引擎. ...

  2. Metasploit3

    1.之前使用的版本是Metasploit2的版本操作系统是基于Ubuntu的,渗透测测试模块也是基于metasploit的,基本上没有设置,Metasploitable3添加了很多安全机制 ,防火墙和 ...

  3. jeecg的开发api接口之旅(http)

    一.接口测试工具 1.postman下载地址:https://download.csdn.net/download/qq_35792159/11898005 2.谷歌浏览器插件:https://www ...

  4. android在主线程下载文件

    android在主线程下载文件 加入以下代码即可if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy polic ...

  5. vue 关于props 父组件传值

    swiper.vue  子组件 info.vue 父组件 swiper.vue<template> <div class="swiper-wrap" @mouse ...

  6. go cache

    go 编译, 或是安装库的时候,产生的日志量很大 go env 删除掉这个log.txt文件,系统空间瞬间就够了

  7. python+selenium+chrome初级自动化操作

    例1. #coding=utf- from selenium import webdriver import os,time chromedriver = "C:\Users\AppData ...

  8. Centos7 安装谷歌浏览器

    配置下载yum源 cd /etc/yum.repos.d vim google-chrome.repo [google-chrome] name=google-chrome baseurl=http: ...

  9. 关于equals和hashcode问题

    默认情况下也就是从超类Object继承而来的equals方法与‘==’是完全等价的,比较的都是对象的内存地址,但我们可以重写equals方法,使其按照我们的需求的方式进行比较,如String类重写了e ...

  10. 第4课.vi编辑器

    1.vi编辑器的配置 cd /etc/vim cp vimrc ~/.vimrc cd ~ gedit .vimrc 在.vimrc中加入如下内容: "关闭兼容功能 set nocompat ...