js事件流、事件委托与事件阶段实例详解

目录
  • 前言
  • 1、事件流
  • 2、事件处理程序
  • 3、事件对象
  • 4、跨浏览器事件处理
  • 5、事件委托
  • 总结

前言

JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻。可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件。本文总结一下 JS 中的事件相关知识点。

1、事件流

HTML 中与 javascript 交互是通过事件驱动来实现的,例如鼠标点击事件 onclick、页面的滚动事件 onscroll 等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。

事件流描述的是从页面中接收事件的顺序,DOM2 级事件流包括下面几个阶段。事件捕获阶段、处于目标阶段、事件冒泡阶段

(1)事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。比如点击页面的一个div触发的元素顺序分别是document、html、body、div。可以在该阶段拦截事件发生

(2)处于目标阶段即捕获到实际的目标元素阶段,

(3)冒泡阶段事件方向传播,从div目标元素传播至document元素

2、事件处理程序

事件处理程序指为响应点击,加载,鼠标等操作而调用的函数。有很多方式指定事件处理程序。

a、通过html元素属性指定事件处理程序

<input type="button" value="点我" onclick="console.log('我被点击了')">

b、DOM0 事件处理程序,通过js获取操作对象元素,并指定事件处理程序

<button id="btn">点我</button>
    <script>
        var btn = document.getElementById("btn")
        btn.onclick = function () {
            console.log("我被点击了");
        }
    </script>

c、DOM2 事件处理程序

addEventListener 和 removeEventListener() 是 DOM2 级事件新增的指定事件处理程序的操作,addEventListener方法都接收 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。IE 只支持事件冒泡。通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener() 并传入与添加时同样的参数来移除。

<button id="btn">点我</button>
    <script>
        var btn = document.getElementById("btn")
        btn.addEventListener("click", function () {
            console.log("我被点击了");
        },false)
    </script>

d、IE 事件处理程序

IE 实现了与 DOM 类似的方法,即 attachEvent() 和 detachEvent() 。这两个方法接收两个同样的参数:事件处理程序的名字和事件处理函数。

<button id="btn">点我</button>
    <script>
        var btn = document.getElementById("btn");
        btn.attachEvent("onclick", function () {
            console.log("我被点击了");
        });
    </script>

在 IE中使用 attachEvent() 与使用 DOM0方式的主要区别是事件处理程序的作用域。使用 DOM0方式时,事件处理程序中的 this 值等于目标元素。而使用 attachEvent() 时,事件处理程序是在全局作用域中运行的,因此 this 等window。

使用 attachEvent() 添加的事件处理程序将使用 detachEvent() 来移除,只要提供相同的参数。

3、事件对象

a、DOM事件对象event

在 DOM 合规的浏览器中, event 对象是传给事件处理程序的唯一参数。

<button id="btn">点我</button>
    <script>
        var btn = document.getElementById("btn")
        btn.addEventListener("click", function (event) {
            console.log(event);
        }, false)
    </script>

打印如下:

b、IE 事件对象

与 DOM 事件对象不同, IE 事件对象可以基于事件处理程序被指定的方式以不同方式来访问。

如果通过DOM方式添加事件处理程序,则event 对象只是 window 对象的一个属性

<button id="btn">点我</button>
    <script>
        var btn = document.getElementById("btn")
        btn.addEventListener("click", function () {
            let event = window.event;
            console.log(event);
        }, false)
    </script>

如果通过IE事件处理程序,则 event对象会作为唯一的参数传给处理函数

<button id="btn">点我</button>
    <script>
        var btn = document.getElementById("btn")
        btn.attachEvent("click", function (event) {
            console.log(event);
        }, false)
    </script>

4、跨浏览器事件处理

// 包含兼容性处理的事件处理函数
const eventUtils={
    //添加事件
    addEvent:function(element,type,handler){
        if (elment.addEventListener) {
            element.addEventListener(type,handler,false)
        } else if(elment.attachEvent){
            element.attachEvent("on"+type,handler)
        }else{
            elment["on"+type]=handler
        }
    },

    //移除事件
    removeEvent:function(element,type,handler){
        if(elment.removeEventListener){
            element.removeEventListener(type,handler,false)
        }else if(element.datachEvent){
            element.datachEvent("on"+type,handler)
        }else{
            element["on"+type]=null
        }
    },
    //获取事件目标元素
    getTarget:function(event){
        return event.target||event.srcElement
    },
    //获取event对象的引用,取到事件的所有信息,确保随时使用event
    getEvent:function(event){
        return event||window.event
    },
    //阻止事件(主要是事件冒泡,因为ie不支持事件捕获)
    stopPropagation:function(event){
        if (event.stopPropagation) {
            event.stopPropagation()
        } else {
            event.cancelBubble=true
        }
    },
    //取消事件的默认行为(主要ie事件对象设置returnValue为false可以取消事件默认行为)
    preventDefault:function(event){
        if (event.preventDefault) {
            event.preventDefault()
        } else {
            event.returnValue=false
        }
    }
}

5、事件委托

简介:事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素 DOM 的类型,来做出不同的响应。

举例:最经典的就是 ul 和 li 标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在 li 标签上直接添加,而是在ul 父元素上添加。因为所有的li标签都是ul标签的后代,在li标签上触发事件时,会进行事件冒泡,必定在ul标签上接收到触发事件处理程序,通过事件对象可以判断具体是哪个li标签触发的,这样就省去了重复获取元素的代码。

好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。减少整个页面所需的内存,提升整体性能

事件委托的实现

我们可以给HTMLElement对象绑定该方法delegate

HTMLElement.prototype.delegate = function(type,selector,fn){
    this.addEventListener(type,function(e){
		var target = e.target,
			bubble = true;

		while(bubble && target !== this){
			if (filter(this,selector,target)) {
				bubble = fn.call(target,e);
			}

			target = target.parentNode;

			return bubble;
		}

    });

    function filter(agent,selector,target){
	var nodes = agent.querySelectorAll(selector);

	for (var i = 0; i < nodes.length; i++) {
		if (nodes[i] == target) return true;
	}

	return false;
    }
}

document.body.delegate('click','.parentNode li',function(e){
	console.log(e.target);
});

实际情况下,有些事件 blurchangefocus 等事件,是不支持事件冒泡的。这里并没有做判断。

总结

到此这篇关于js事件流、事件委托与事件阶段的文章就介绍到这了,更多相关js事件流、事件委托与事件阶段内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入理解JS的事件绑定、事件流模型

     一.JS事件 (一)JS事件分类 1.鼠标事件: click/dbclick/mouseover/mouseout 2.HTML事件: onload/onunload/onsubmit/onresize/onchange/onfoucs/onscroll 3.键盘事件: keydown:键盘按下时触发  keypress:键盘按下并抬起的瞬间触发.  keyup:键盘抬起触发 [注意事项] ①执行顺序:keydown keypress keyup ②keypress只能捕获数字,字母,符号键,

  • JavaScript中的事件委托及好处

    1,什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件. 也就是:利用冒泡的原理,把事件加到父级上,触发执行效果. 好处呢:1,提高性能. 我们可以看一个例子:需要触发每个li来改变他们的背景颜色. <ul id="ul"> <li>aaaaaaaa</li> <li>bbbbbbbb&l

  • JS 事件绑定、事件监听、事件委托详细介绍

    在JavaScript的学习中,我们经常会遇到JavaScript的事件机制,例如,事件绑定.事件监听.事件委托(事件代理)等.这些名词是什么意思呢,有什么作用呢? 事件绑定 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称. 在JavaScript中,有三种常用的绑定事件的方法: 在DOM元素中直接绑定: 在JavaScript代码中绑定: 绑定事件监听函数. 在DOM中直接绑定事件

  • js中的事件委托或是事件代理使用详解

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了

  • Javascript 事件流和事件绑定

    事件流 浏览器中的事件流意味着页面上可有不仅一个,甚至多个元素响应同一个事件.而这一个或多个元素响应事件发生的先后顺序在各个浏览器(主要针对IE和Netscape)上是不同的. 冒泡型事件(Dubbed Bubbling) IE上的解决方案就是冒泡型事件(Dubbed Bubbling).冒泡型事件的基本思想是,事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. 示例(1):点击我触发冒泡型事件流 示例(1)的XHTML代码结构:<span id="cnt0

  • JavaScript动态添加事件之事件委托

    先给大家讲下什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件. 也就是:利用冒泡的原理,把事件加到父级上,触发执行效果. 其所谓的动态添加事件实质就是指js中的事件委托. 我们知道在js中,事件处理只能绑定在当前被选中的元素上,换句话也就是说,事件处理只能绑定在当前文档已经存在的元素上!但是,往往小伙伴们都会遇到一个问题就是,我的元素是后来动态

  • javascript事件委托的方式绑定详解

    js事件绑定 事件绑定,这里使用了冒泡的原理,从点击的元素开始,递归方式的向父元素传播事件,这样做的好处是对于大量要处理的元素,不必为每个元素都绑定事件,只需要在他们的父元素上绑定一次即可,提高性能.还有一个好处就是可以处理动态插入dom中的元素,直接绑定的方式是不行的. 之前一直使用的是jquery的on方法做这样的事情,前几天看到公司项目中有实现这种方式的源代码,拿来仔细研究研究,跟大家分享分享. function $bindAction(dom, event, listeners) { #

  • JS中获取 DOM 元素的绝对位置实例详解

    在操作页面滚动和动画时经常会获取 DOM 元素的绝对位置,例如 本文 左侧的悬浮导航,当页面滚动到它以前会正常地渲染到文档流中,当页面滚动超过了它的位置,就会始终悬浮在左侧. 本文会详述各种获取 DOM 元素绝对位置 的方法以及对应的兼容性.关于如何获取 DOM 元素高度和滚动高度,请参考视口的宽高与滚动高度 一文. 概述 这些是本文涉及的 API 对应的文档和标准,供查阅: API 用途 文档 标准 offsetTop 相对定位容器的位置 MDN CSSOM View Module clien

  • JS图片轮播与索引变色功能实例详解

    废话不多说了,直接给大家贴代码了,具体代码如下所示: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <met

  • JS技巧Canvas 性能优化脏矩形渲染实例详解

    目录 正文 画布该如何更新? 脏矩形渲染原理 脏矩形渲染实现 性能测试 结尾 正文 使用 Canvas 做图形编辑器时,我们需要自己维护自己的图形树,来保存图形的信息,并定义元素之间的关系. 我们改变画布中的某个图形,去更新画布,最简单的是清空画布,然后根据图形树将所有图形再绘制一遍,这在图形较少的情况下是没什么问题的.但如果图形数量很多,那绘制起来可能就出现卡顿了. 那么,有没有什么办法来优化一下?有,脏矩形渲染. 画布该如何更新? 这里我们假设这么一个场景,画布上绘制了随机位置大量的绿球,然

  • js事件流、事件委托与事件阶段实例详解

    目录 前言 1.事件流 2.事件处理程序 3.事件对象 4.跨浏览器事件处理 5.事件委托 总结 前言 JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻.可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件.本文总结一下 JS 中的事件相关知识点. 1.事件流 HTML 中与 javascript 交互是通过事件驱动来实现的,例如鼠标点击事件 onclick.页面的滚动事件 onscroll 等等,可以向文档或者文档中的元素添加事件侦听

  • Springboot事件和bean生命周期执行机制实例详解

    目录 @PostConstruct执行机制 ContextRefreshedEvent事件机制 ApplicationStartedEvent事件机制 总结 细节问题 原因 @PostConstruct执行机制 进入SpringApplication#run(java.lang.String…) public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); st

  • Angular.Js中过滤器filter与自定义过滤器filter实例详解

    本文主要给大家介绍了Angular.Js过滤器filter与自定义过滤器filter的相关内容,分享出来供大家参考学习,下面来看看详细的介绍: 一.AngularJS的filter过滤器: uppercase|lowercase:大小写转换过滤 json:json格式过滤 date:日期格式过滤 number:数字格式过滤 currency:货币格式过滤 filter:查找 limitTo:字符串对象截取 orderBy:对象排序 <!DOCTYPE html> <html lang=&

  • Java IO流对象的序列化和反序列化实例详解

    Java-IO流 对象的序列化和反序列化 序列化的基本操作 1.对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化. 2.序列化流(ObjectOutputStream),writeObject 方法用于将对象写入输出流中: 反序列化流(ObjectInputStream),readObject 方法用于从输入流中读取对象. 3.序列化接口(Serializeable) 对象必须实现序列化接口,才能进行序列化,否则会出现异常.这个接口没有任何方法,只是一个标准. packag

  • Vue.js 单页面多路由区域操作的实例详解

    单页面多路由区域操作 在一个页面中有两个及以上的<router-view>区域,需要通过设置路由的index.js,来操作这些区域的内容 App.vue 中设置: <router-view></router-view> <router-view name="left" style="float: left;width: 50%; height: 300px;background-color: #ccc;"></r

  • JS/HTML5游戏常用算法之追踪算法实例详解

    本文实例讲述了JS/HTML5游戏常用算法之追踪算法.分享给大家供大家参考,具体如下: 追踪算法在动作游戏中非常常见,从很早的游戏<吃豆人>到大型的街机机战类游戏,到处可见追踪效果的身影.一个好的追踪算法将会大大提高游戏的可玩性和玩家的兴趣. [简单算法] 先来看一个简单的跟踪算法,如下图所示,假设在canvas坐标系中存在物体A和B,物体A将把B作为追踪目标,物体在二维空间中的运动可以分解为坐标系中X.Y轴的运动,其在X和Y方向的速度决定了物体运行的方向和速率.别忘了,速度是有方向和大小的,

  • JS遍历DOM文档树的方法实例详解

    本文实例讲述了JS遍历DOM文档树的方法.分享给大家供大家参考,具体如下: 一 介绍 遍历文档树通过使用parentNode属性.firstChild属性.lastChild属性.previousSibling属性和nextSibling属性来实现. 1.parentNode属性 该属性返回当前节点的父节点. [pNode=]obj.parentNode pNode:该参数用来存储父节点,如果不存在父节点将返回"null". 2.firstChild属性 该属性返回当前节点的第一个子节

随机推荐