js 事件流(冒泡、捕获)与绑定事件方法

2023-05-16

一:事件流

事件流描述的是从页面中接收事件的顺序。但 IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事件捕获流。

1.事件冒泡

IE 的事件流叫做事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
在这里插入图片描述
如果click页面中的div元素,先是触发div上的绑定事件,然后是body上的绑定事件,再然后是html,知道document对象。

IE9、Firefox、Chrome 和 Safari 将事件一直冒泡到 window 对象。

2.事件捕获

事件捕获与事件冒泡相反,认为最不具体的节点应该更早接收事件。
在这里插入图片描述
如果click页面中的div元素,先是由document节点接收到事件,然后是html,再然后是body触发事件,最后是div元素触发事件。

IE9、Safari、Chrome、Opera和 Firefox 目前也都支持这种事件流模型,但是都是从window对象开始接收事件。

3.DOM事件流

DOM2级事件规定,事件流包括3个阶段,(捕获阶段、目标阶段、冒泡阶段)。
在这里插入图片描述
用户操作事件开始,先是捕获,从document节点开始,到div节点之前,捕获结束,开始目标阶段,表示div节点接收到事件,然后开始冒泡。

“DOM2 级事件”规范明确要求捕获阶段不会涉及事件目标,就是在捕获阶段不会触发绑定事件。在冒泡阶段会触发绑定事件(目标阶段属于冒泡阶段),如上图点击div元素,会在4,5,6,7触发绑定事件,1,2,3则不触发

IE9、Safari、Chrome、Firefox 和 Opera 9.5 及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件。IE8不支持DOM事件流。

二.绑定事件

1.DOM0级绑定事件

    //输出Click Me1。this为绑定事件目标元素
    <input type="button" value="Click Me1" onclick="console.log(this.value)" />

	//输出Click Me2。event为绑定事件节点对象
    <input type="button" value="Click Me2" onclick="console.log(event.target.value)" />
		
    <input type="button" value="Click Me3" onclick="clickMe3(event)" />

	<input type="button" value="Click Me4" id="clickMe4"/>
    <script>
        function clickMe3 (event){
        	console.log(this)   //this指向window
            console.log(event.target.value)   //输出Click Me3。event.target为绑定事件目标元素
        }

        var btn = document.getElementById("clickMe");
        btn.onclick = function(event){
            console.log(this)   //this指向绑定元素
            console.log(event)	//event为绑定事件节点对象
        }
    </script>

若使用clickMe3的绑定事件方法需注意函数内的this指向,它指向window,作用域为全局。

DOM0级绑定事件方法不能在其中使用未经转义的 HTML 语法字符,例如和号(&)、双引号(" ")、小于号(<)或大于号(>)。可转义后使用,如下

<input type="button" value="Click Me" onclick="alert(&quot;Clicked&quot;)" />

DOM0级绑定事件方法应用很广泛。
需注意的是,如果js内容过多或其他异步问题,导致绑定事件时并不及时,可能造成DOM元素渲染完成后短时间内并没有绑定事件,用户点击了并没有效果。

若要解除绑定 btn.onclick = null 即可。

2.DOM2 级事件处理程序

addEventListener()和removeEventListener()为DOM2级事件,每个DOM都有这两个方法,且接收3个参数(事件名,回调函数,布尔值)

    <input type="button" value="Click Me" id="clickMe"/>
    <script>
        var btn = document.getElementById("clickMe");
        btn.addEventListener("click",function(event){
            console.log(this) // this指向绑定事件元素
            console.log(event) // event指向绑定节点对象
        },false)
    </script>

addEventListener()三个参数中,click为触发事件类型,回调函数为触发事件后的回调,布尔值为表示在什么阶段触发,为true时在捕获阶段触发,为false时在冒泡阶段触发。可省略,默认为false



        var btn = document.getElementById("clickMe");
        function clickMe() {
            console.log("click Me")
        }
        btn.addEventListener("click", clickMe, false)
        
        //无法解除绑定
        // btn.removeEventListener("click", function () {
        //     console.log("click Me")
        // }, false)

		//可以解除绑定
        btn.removeEventListener("click", clickMe, false)

removeEventListener()方法为解除事件绑定,与addEventListener()用法一样。不可将回调函数写成匿名函数,不然无法解除绑定


    <input type="button" value="Click Me" id="clickMe"/>
    <script>
        var btn = document.getElementById("clickMe");
        btn.addEventListener("click",function(){
            console.log(1)
        },false)
        btn.addEventListener("click",function(event){
            console.log(2)
        },false)
    </script>

多次绑定将会多次触发,按照绑定顺序先输出1,后输出2

3.IE绑定事件

IE浏览器的DOM元素都有attachEvent()和 detachEvent()方法。接收两个参数(绑定事件,回调函数),因为IE8及以前版本只支持冒泡事件,所以attachEvent()方法会在冒泡阶段触发。

	<input type="button" value="Click Me" id="clickMe"/>
    <script>
        var btn = document.getElementById("clickMe");
        btn.attachEvent("onclick",function(){
            console.log(this) // this指向window
        })
        btn.detachEvent("onclick",function(event){
            console.log(event) //event指向绑定事件节点对象
        })
        
        function removeClickMe(){
			console.log("remove")
		}
		btn.attachEvent("onclick",removeClickMe)
		btn.detachEvent("onclick",removeClickMe)
    </script>

1.attachEvent()方法中htis指向window
2.绑定事件名需要加‘on’
3.IE8及以前多次绑定触发顺序为先绑定、后触发(先输出event,后输出this)
4.IE8以后多出绑定触发顺序为先绑定,先触发(先输出this,后输出event)
5,removeClickMe()方法删除时不允许使用匿名函数

4.跨浏览器绑定事件方法兼容

    <input type="button" value="Click Me" id="clickMe" />
    <script>
        var btn = document.getElementById("clickMe");

        //兼容绑定事件方法
        function addHandler(element, type, handler) {
            if (element.addEventListener) {
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent("on" + type, handler);
            } else {
                element["on" + type] = handler;
            }
        }

        //兼容解绑事件方法
        function removeHandler(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.detachEvent) {
                element.detachEvent("on" + type, handler);
            } else {
                element["on" + type] = null;
            }
        }
        //定义事件回调函数
        var handler = function (event) {
            console.log(this); //this指向绑定事件元素
            console.log(event); // event指向绑定事件节点对象
        };
        //调用绑定
        addHandler(btn, "click", handler);
    </script>

这两个方法接受 3 个参数:要操作的元素、事件名称和事件处理程序函数。

三.事件对象

1.event 对象

上面代码中出现的event是当前绑定事件的节点对象,这个对象中包含着所有与事件有关的信息。如图

在这里插入图片描述

2.event对象包含的常用属性及方法

event.target
等价于之前代码中的this,也就是绑定事件的元素本身,打印效果如图
在这里插入图片描述

IE中使用event.srcElement来获取元素目标


event.preventDefault()
阻止默认行为,可以阻止a标签的href的默认跳转等默认行为

IE中使用event.returnValue = false来达到阻止默认行为的效果


event.stopPropagation()
该方法用于立即停止事件在 DOM 层次中的传播,即取消进一步的事件捕获或冒泡

    <input type="button" value="Click Me" id="clickMe" />
    <script>
        var btn = document.getElementById("clickMe");
        btn.onclick = function (event) {
            console.log("Clicked");//输出Clicked
            event.stopPropagation();//阻止了事件流的冒泡行为
        };
        document.body.onclick = function (event) {
            console.log("Body clicked");//不执行
        };
    </script>

body上的绑定事件将不执行、

PS:欢迎大家指正补充

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js 事件流(冒泡、捕获)与绑定事件方法 的相关文章

  • Lua 模块与包

    Lua 模块与包 参考至菜鸟教程 模块类似于一个封装库 xff0c 从 Lua 5 1 开始 xff0c Lua 加入了标准的模块管理机制 xff0c 可以把一些公用的代码放在一个文件里 xff0c 以 API 接口的形式在其他地方调用 x
  • Lua 文件I/O

    Lua 文件I O 参考至菜鸟教程 Lua I O 库用于读取和处理文件 分为简单模式 xff08 和C一样 xff09 完全模式 简单模式 xff08 simple model xff09 拥有一个当前输入文件和一个当前输出文件 xff0
  • Lua 错误处理

    Lua 错误处理 参考至菜鸟教程 程序运行中错误处理是必要的 xff0c 在我们进行文件操作 xff0c 数据转移及web service 调用过程中都会出现不可预期的错误 如果不注重错误信息的处理 xff0c 就会造成信息泄露 xff0c
  • Lua 调试(Debug)

    Lua 调试 Debug 参考至菜鸟教程 Lua 提供了 debug 库用于提供创建我们自定义调试器的功能 Lua 本身并未有内置的调试器 xff0c 但很多开发者共享了他们的 Lua 调试器代码 Lua 中 debug 库包含以下函数 x
  • Lua 垃圾回收

    Lua 垃圾回收 参考至菜鸟教程 Lua 采用了自动内存管理 这意味着你不用操心新创建的对象需要的内存如何分配出来 xff0c 也不用考虑在对象不再被使用后怎样释放它们所占用的内存 Lua运行了一个垃圾收集器来收集所有死对象 xff08 即
  • Lua 面向对象(详解)

    Lua 面向对象 xff08 详解 xff09 参考文章 xff1a https blog csdn net linxinfa article details 103254828 https zhuanlan zhihu com p 115
  • Lua实现矩阵的加减乘除

    Lua实现矩阵的加减乘除 参考文章 xff1a https blog csdn net qq 54180412 article details 122943327 https www bilibili com video BV1434y18
  • ubuntu系统配置大恒相机驱动并读取ros话题

    文章目录 0 说明1 安装大恒相机sdk1 1 下载1 2 安装sdk 用于配置ip和调试相机参数 1 电脑网卡配置 网卡固定ip 2 查看相机图像以及配置相机参数 2 安装ros驱动包 注 xff1a 大恒相机官方没ros驱动 2 0 正
  • C++类对象与Lua之间的交互

    C 43 43 类对象与Lua之间的交互 C语言与Lua进行交互 xff0c 我们可以相对轻易的做到 xff0c 但在实际应用中我们更加偏向于使用C 43 43 与Lua进行交互 xff0c 面向对象编程 关于C语言与Lua之间的调用交互实
  • C++与Lua交互实例 -- 矩阵的加减乘除(版本一)

    C 43 43 与Lua交互实例 矩阵的加减乘除 xff08 版本一 xff09 关于lua中封装的类模板以及相关知识可参考以下链接 xff1a https ufgnix0802 blog csdn net article details
  • C++与Lua交互实例 -- 矩阵的加减乘除(版本二)

    C 43 43 与Lua交互实例 矩阵的加减乘除 xff08 版本二 xff09 TIPS xff1a 关于使用矩阵的加减乘除测试C 43 43 与Lua的交互以及下面没讲述到的知识点可以阅读第一版 xff1a https blog csd
  • Windows下LuaBridge2.8的环境配置及简单应用

    Windows下LuaBridge2 8的环境配置及简单应用 LuaBridge2 8下载链接 xff1a https github com vinniefalco LuaBridge tags 关于Lua的环境配置可参考以下链接 xff0
  • Lua 开发过程中常见坑

    Lua 开发过程中常见坑 Lua next span class token keyword return span G span class token punctuation span span class token function
  • 私网与公网地址转换

    私网与公网地址转换 NAT概述NAT功能静态NAT动态NATEASYIP xff08 多个内网地址对一个接口 xff09 PAT端口多路复用 NAT概述 NAT xff08 Network Address Translation xff0c
  • VWmare安装CentOS7及连接Xshell超详细过程(图文)

    VWmare安装CentOS7及连接Xshell超详细过程 xff08 图文 xff09 前言一 准备工作二 安装虚拟机过程 1 选择文件 xff0c 新建虚拟机 2 选择配置类型 3 自定义硬件配置 4 进入系统安装界面 二 连接Xshe
  • rpm与yum

    rpm与yum 前言一 应用程序与命令系统的关系二 典型应用程序的目录结构三 常见的软件封装类型四 rpm 1 概述 2 命令概述 3 查询rpm软件包信息 查询已安装的rpm软件信息 查询未安装的rpm软件包文件中的信息 安装 升级 卸载
  • Linux用户与权限管理

    Linux用户与权限管理 前言一 管理用户账号 1 用户账号概述 用户标识UID xff08 User IDentity xff0c 用户标识号 xff09 用户账号文件 2 用户账号管理 添加用户账号 xff08 useradd xff0
  • yum源仓库

    yum源仓库 前言一 yum介绍一 yum源的提供方式 1 配置本地仓库 2 配置ftp源 三 yum命令 1 yum常用的操作 2 搜索软件包命令 3 安装升级 4 软件卸载 5 yun history命令 总结 前言 yum相对与rpm
  • C++常见问题的总结

    1 C语言跟C 43 43 的关系 xff1a xff08 1 xff09 C语言跟C 43 43 的本质区别 xff1a 1 xff09 c更倾向于面向过程 xff0c c 43 43 是面向过程 43 面向对象 43 泛型编程 2 xf

随机推荐

  • Nginx Rewrite

    Nginx Rewrite 前言一 nginx rewrite概述 1 概述 2 跳转场景 3 跳转实现 4 rewrite实际场景 nginx跳转需要的实现方式 rewrite放在server if location 段中 对域名或参数字
  • Dockerfile概念简介

    Dockerfile概念简介 前言一 dockerfile概念二 Docker镜像的创建 1 基于现有镜像创建 2 基于本地模板创建 3 基于dockerfile创建 dockerfile结构 xff08 四部分 xff09 构建镜像命令
  • 【云原生之k8s】k8s基础详解

    云原生之k8s k8s基础详解 前言一 kubernetes介绍 1 kubernetes简介 2 应用部署方式的演变 二 kubernetes组件 1 kubernetes架构 2 master组件 apiserver controlle
  • 【云原生之k8s】kubeadm搭建k8s集群

    云原生之k8s kubeadm搭建k8s集群 前言一 集群介绍 1 集群搭建方法 2 集群架构 二 集群部署 1 环境部署 所有节点 xff0c 关闭防火墙规则 xff0c 关闭selinux xff0c 关闭swap交换 修改主机名 xf
  • 【云原生之k8s】k8s管理工具kubectl详解

    云原生之k8s k8s管理工具kubectl详解 前言一 陈述式管理 1 陈述式资源管理方法 2 k8s相关信息查看 查看版本信息 查看节点信息 查看资源对象简写 查看集群信息 配置kubectl自动补全 查看日志 基本信息查看1 查看ma
  • 关于结构体指针与STM32外设的笔记

    96 define RCC RCC TypeDef RCC BASE xff09 96 逐步分解这句代码的含义 RCC TypeDef RCC BAS 其中 RCC BAS定义为 define RCC BASE AHBPERIPH BASE
  • visual studio与visual c++ 6.0的区别

    xfeff xfeff Visual Studio支持多种语言 xff0c Visual C 43 43 6 0 只支持C和C 43 43 Visual C 43 43 6 0 是Visual Studio 6 0的一个组成部分 xff0c
  • GD32F303 移植 FreeRTOS

    文章目录 1 准备工作1 1 软件版本1 2 源码下载1 3 基础工程 3 FreeRTOS 移植3 1 复制需要的内核文件3 2 添加文件到 Keil 工程3 3 添加 FreeRTOSConfig h 内核配置文件3 4 配置任务调度相
  • FreeRTOS 之 heap_4 踩坑之路

    参考博文连接 xff1a FreeRTOS系列 heap 4 c 内存管理分析FreeRTOS Heap 1 2 3 4 5 比较 示例工程代码库地址如下 xff1a GiteeGit 1 问题描述 博主在使用 heap 4 的 pvPor
  • GD32F30x Keil 环境下在 FreeRTOS 任务中使用浮点运算报 HardFault 异常的问题(二)

    文章目录 1 问题描述1 1 环境1 2 问题 2 参考资料3 来龙去脉3 1 定位问题3 2 xPortPendSVHandler3 3 EXC RETURN3 4 寄存器3 5 探索真像3 5 1 浮点任务切换到空闲任务3 5 2 空闲
  • 辛勤劳作

    本文只有在12月27日可以学习到 我对敬业的体会是 xff1a 正在从事的工作就是自己的生命 xff0c 它意味着每周7天 xff0c 每年52周一心扑在上面 写下上面这句话 xff0c 我的泪水差一点儿就涌了出来 14年的寿险生涯 xff
  • 无人机开发资料推荐

    作者 xff1a BlueSky 链接 xff1a https www zhihu com question 30084079 answer 52762050 来源 xff1a 知乎 著作权归作者所有 商业转载请联系作者获得授权 xff0c
  • STM32移植使用mbedtls-2.24.0

    STM32移植使用mbedtls 2 24 0 目录 STM32移植使用mbedtls 2 24 0 xff08 1 xff09 关于PolarSSL xff08 2 xff09 mbedtls移植 xff08 3 xff09 移植测试 扫
  • C++中的 ::

    C 43 43 中的双冒号 第一种 xff0c 类作用域 xff0c 用来标明类的变量 函数 Human span class token operator span span class token function setName sp
  • 算法的类型:

    所有的算法可以大概分为以下三种类型 xff1a 1 xff0e 贪婪算法 greedy algorithm 该算法每一步所做的都是当前最紧急 最有利或者最满意的 xff0c 不会考虑所做的后果 xff0c 直到完成任务 这种算法的稳定性很差
  • 平衡三棱柱原理

    先用一个例子来解释角动量守恒 大家一定都知道直升机 xff0c 直升机除了机身上方有一个大的螺旋桨外其尾部也有一个螺旋桨 这个螺旋桨的作用就是用来保持机身不会转动的 xff0c 如果没有它 xff0c 当直升机上方的螺旋桨转动时 xff0c
  • 自抗扰控制(ADRC)

    1 ADRC控制原理和结构 xff08 1 xff09 最速跟踪微分器 TD xff08 2 xff09 扩张状态观测器 ESO xff08 3 xff09 非线性状态误差反馈 NLSEF 2 ADRC控制仿真 xff08 1 xff09
  • 深度学习算法归类

    监督式学习 xff1a 逻辑回归 xff08 Logistic Regression xff09 和反向传递神经网络 xff08 Back Propagation Neural Network xff09 非监督式学习 xff1a Apri
  • DQN代码-ROS-turtlebot3

    DQN代码解析 代码来自turtlebot3 qdn environment stage 4 py 发布话题 xff1a cmd vel 订阅话题 xff1a odom 服务话题 gazebo reset simulation gazebo
  • js 事件流(冒泡、捕获)与绑定事件方法

    一 xff1a 事件流 事件流描述的是从页面中接收事件的顺序 但 IE 的事件流是事件冒泡流 xff0c 而 Netscape Communicator 的事件流是事件捕获流 1 事件冒泡 IE 的事件流叫做事件冒泡 xff0c 即事件开始