摘要:可以用于事件处理函数中阻止冒泡行为。事件代理的原理和问题在我们了解了事件流之后,事件代理的原理就很好理解了,其实就是事件冒泡会触发容器的相关事件并执行监听函数。给注销事件绑定。如果此事件正在执行,会立即停止。
有如下 html 片段
要对 li 添加 click 事件。通常做法:
var list = document.getElementsByTagName("li"); for (var i = 0; i < list.length; i++) { list[i].addEventListener("click", function(e) { console.log(e.target.textContent); }) }
事件代理的做法
var ul = document.getElementsByTagName("ul")[0]; ul.addEventListener("click", function(e) { if (e.target.tagName === "LI") { console.log(e.target.textContent); } })
我们来对比一下两段注册点击事件的代码。第一段代码很常规,直接找到相关元素然后一一绑定。第二段代码看起来简洁一点,但多了一层判断。
做一个简单的 delegate 封装
EventTarget.prototype.delegate = function(targetDom, type, listener) { this.addEventListener(type, function(e) { if (e.target.tagName === targetDom.toUpperCase()) { listener(e); } }); } var ul = document.getElementsByTagName("ul")[0]; ul.delegate("li", "click", function(e) { console.log(e.target.textContent); });
接下来的篇幅主要会聊到事件流,事件代理的原理和问题,event 和 EventTarget 帮你深度了解 js 的事件。
事件触发的流程通常我们把事件流分为三个阶段
var ul = document.getElementsByTagName("ul")[0]; ul.addEventListener("click", function(e) { if (e.target.tagName === "LI") { console.log(e.target.textContent); } }) document.body.addEventListener("click", function(e) { console.log("body", e.target.textContent); })
捕获阶段:这个就是向下去找触发事件的元素。但是一定注意如果这个时候 body 上的 click 并不会触发。如果希望 body 上的 click 先触发,就需要给 addEventListener 第三个参数 useCapture 设置为 true (dom3 引入的,所以比较新的浏览器才有效)。
目标阶段:执行目标的绑定函数
冒泡阶段:沿着父级元素一路向上,body 上如果也有 click 事件就会执行。event.stopPropagation() 可以用于事件处理函数中阻止冒泡行为。
事件代理的原理和问题在我们了解了事件流之后,事件代理的原理就很好理解了,其实就是事件冒泡会触发容器 dom 的相关事件并执行监听函数。
那事件代理会带来什么问题呢?
如果 ul 有 click ,并且在它上面为 li 做了 click 事件的代理。这个时候其实我只想触发 li 的 click。解决方法如下:
var ul = document.getElementsByTagName("ul")[0]; ul.addEventListener("click", function(e) { if (e.target === e.currentTarget) { console.log(e.target); } }); ul.delegate("li", "click", function(e) { console.log(e.target); });
很显然 stopPropagation 并不能解决问题,这里通过比较 target 和 currentTarget 来判断当前事件触发元素(target)是否是注册事件的元素(currentTarget)即可。
stopPropagation,target,currentTarget 都是 event 的方法和属性,所以下面详细讲讲 event 对象。
event 事件对象详解 常用属性:currentTarget 注册事件的 dom 元素
srcElement ie6-8 的触发事件的 dom 元素,非标准
target 触发事件的 dom 元素
timeStamp 返回事件发生时的时间戳
type 事件的类型
常用方法preventDefault() 阻止默认行为。例如 a 标签默认会跳转 href 指定的链接,执行该方法可以阻止跳转的发生。
stopImmediatePropagation() 阻止冒泡行为,并立即阻止该绑定元素上的相同类型事件处理函数的执行。立即阻止的意义在于,本方法执行之前函数执行或者其他的相同类型绑定不会有问题,但一旦执行该方法后面的程序将不再执行。例子
stopPropagation() 阻止冒泡行为。
EventTarget我们来看一下 mdn 对于 EventTarget 的定义:
一个EventTarget是一个可以接受DOM事件且能绑定事件监听器的对象.最常见的EventTarget就是DOM元素对象,另外,还有一些不是DOM元素的对象也能成为EventTarget,比如document, window, XMLHttpRequest,等等.
EventTarget 有三个常用方法:
addEventListener(type, listener[, useCapture])
给 EventTarget 添加事件绑定,type 为事件类型(例如 ‘click’),listener 事件触发时的处理函数(默认参数 event 本文后面会讲到)。useCapture 是一个非必需的布尔值,默认为 false。如果设置为 true 即表示希望发起捕获(关于捕获,会在后面的事件触发流程里讲到)。
removeEventListener(type, listener[, useCapture])
给 EventTarget 注销事件绑定。参数和 addEventListener 相同。需要特别注意两点。
1、如果同一个监听事件分别为“事件捕获”和“事件冒泡”注册了一次,一共两次,这两次事件需要分别移除。两者不会互相干扰。 2、如果此事件正在执行,会立即停止。
dispatchEvent
手动触发事件,举个例子(来自 mdn):
var event = new Event("build"); // Listen for the event. elem.addEventListener("build", function (e) { console.log(e.target) }, false); // Dispatch the event. elem.dispatchEvent(event);
上面这个例子就是一个简单的自定义事件,如果想深入了解可以看张鑫旭的漫谈js自定义事件、DOM/伪DOM自定义事件
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/79747.html
摘要:可选,布尔值,指定事件是否在捕获或冒泡阶段执行,默认冒泡。适用范围参数介绍必须,字符串,事件名称。必须,指定事件触发时执行的函数。事件冒泡事件冒泡与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。 什么是事件 javascript与HTML之间交互就是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。事件在浏览器中是以对象的形式存在的,即event,...
摘要:开工荒了两天,赶紧开始为什么写事件代理冒泡捕获,首先冒泡和捕获是事件的核心基础,事件代理原理来自冒泡和捕获。感谢阅读,欢迎吐槽谢谢 2019开工荒了两天,赶紧开始! 为什么写事件代理、冒泡、捕获,首先冒泡和捕获是js事件的核心基础,事件代理原理来自冒泡和捕获。 此文章略过标准浏览器和非标准浏览器的事件流讲解,原因很简单我们现在已经幸福了,已经不考虑IE6、7、8了 直接说现代浏览器事件...
摘要:原文浏览器事件之间的关系程序采用了异步事件驱动编程模型,维基百科对它的解释是事件驱动程序设计英语是一种电脑程序设计模型。 原文:https://keelii.github.io/2016/09/29/javascript-browser-event/ JavaScript、浏览器、事件之间的关系 JavaScript 程序采用了异步事件驱动编程(Event-driven program...
摘要:在他的重学前端课程中提到到现在为止,前端工程师已经成为研发体系中的重要岗位之一。大部分前端工程师的知识,其实都是来自于实践和工作中零散的学习。一基础前端工程师吃饭的家伙,深度广度一样都不能差。 开篇 前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。 winter在他的《重学前端》课程中提到: 到现在为止,前端工程师已经成为研...
摘要:在他的重学前端课程中提到到现在为止,前端工程师已经成为研发体系中的重要岗位之一。大部分前端工程师的知识,其实都是来自于实践和工作中零散的学习。一基础前端工程师吃饭的家伙,深度广度一样都不能差。开篇 前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。 winter在他的《重学前端》课程中提到: 到现在为止,前端工程师已经成为研发体系...
阅读 983·2021-11-18 13:23
阅读 686·2021-11-08 13:16
阅读 821·2021-10-11 10:58
阅读 3474·2021-09-22 15:26
阅读 1680·2021-09-08 10:42
阅读 1764·2021-09-04 16:45
阅读 1702·2019-08-30 15:54
阅读 2536·2019-08-30 13:45