详解JavaScript 事件流


Posted in Javascript onSeptember 02, 2020

事件

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

事件流

事件流描述的就是从页面中接收事件的顺序。而早期的IE和Netscape提出了完全相反的事件流概念,IE事件流是事件冒泡,而Netscape的事件流就是事件捕获。

事件流类别

事件冒泡

即从下至上,从目标触发的元素逐级向上传播,直到window对象。

详解JavaScript 事件流

事件捕获

即从上至下,从document逐级向下传播到目标元素。

详解JavaScript 事件流

后来ECMAScript在DOM2中对事件流进行了进一步规范,基本上就是上述二者的结合。

DOM2级事件规定的事件流包括三个阶段:

  1. 事件捕获阶段
  2. 处于目标阶段
  3. 事件冒泡阶段

注意⚠️:先捕获后冒泡,但是在目标节点上谁写在前面谁先执行。但是在目标元素上不区分冒泡还是捕获,按绑定的顺序来执行。

详解JavaScript 事件流

DOM事件级别

分为四个级别

详解JavaScript 事件流

DOM0:不是W3C规范。

DOM1:开始是W3C规范。专注于HTML文档和XML文档。

DOM2:对DOM1增加了样式表对象模型

DOM3:对DOM2增加了内容模型 (DTD 、Schemas) 和文档验证。

DOM0级

DOM0级事件具有极好的跨浏览器优势,会以最快的速度绑定。绑定方式有如下两种

行内绑定(内联模型)

将函数名直接作为html标签中属性的属性值。

<div onclick="btnClick()">按钮</div>
<script>
function btnClick(){
  console.log("hello");
}
</script>

动态绑定(脚本模型)

通过在JS中选中某个节点,然后给节点添加onclick属性

<div id="btn">按钮</div>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
  console.log("点击");
}
</script>

注意⚠️

  • DOM0级同一个节点只能添加一次同类型事件,后添加的同类型事件会覆盖前面的事件
  • DOM0级只支持冒泡

DOM1级

其中DOM1级事件处理标准中并没有定义事件相关的内容,所以没有所谓的DOM1事件处理

DOM2级

DOM2级定义了两个事件处理程序。(观察者模式)

  • addEventListener() ---添加事件侦听器
  • removeEventListener() ---删除事件侦听器

函数均有3个参数, 第一个参数是要处理的事件名 第二个参数是作为事件处理程序的函数 第三个参数是一个boolean值,默认false表示使用冒泡机制,true表示捕获机制。

<div id="btn">按钮</div>
<script>
var btn=document.getElementById("btn");
btn.addEventListener("click",hello,false);
btn.addEventListener("click",helloagain,false);
function hello(){
  console.log("hello");
}
function helloagain(){
  console.log("hello again");
}
</script>
// 点击后结果: 
// hello
// hello again

注意⚠️

如果定义了一模一样的监听方法时,是会发生覆盖的。

<div id="btn">点击</div>

<script>
var btn=document.getElementById("btn");
btn.addEventListener("click",hello,false);
btn.addEventListener("click",hello,false);
function hello(){
  console.log("hello");
}
</script>
// 点击后结果: 
// hello

DOM3级

对DOM2增加了内容模型 (DTD 、Schemas) 和文档验证。定义了一些新的事件,比如键盘事件,还可以自定义事件。

自定义事件

自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件。要创建的自定义事件可以由createEvent("CustomEvent"); 返回的对象有一个initCustomEvent()方法接收如下四个参数。

  • type:字符串,触发的事件类型,自定义。例如 “keyDown”,“selectedChange”;
  • bubble(布尔值):标示事件是否应该冒泡;
  • cancelable(布尔值):标示事件是否可以取消;
  • detail(对象):任意值,保存在event对象的detail属性中;

可以像分配其他事件一样在DOM中分派创建的自定义事件对象。如:

var div = document.getElementById("myDiv");
EventUtil.addEventHandler(div,"myEvent", function () {
 alert("div myEvent!");
});
EventUtil.addEventHandler(document,"myEvent",function(){
 alert("document myEvent!");
});
if(document.implementation.hasFeature("CustomEvents","3.0")){
 var e = document.createEvent("CustomEvent");
 e.initCustomEvent("myEvent",true,false,"hello world!");
 div.dispatchEvent(e);
}

这个例子中创建了一个冒泡事件“myEvent”。而event.detail的值被设置成了一个简单的字符串,然后在div和document上侦听该事件,因为在initCustomEvent中设置了事件冒泡。所以当div激发该事件时,浏览器会将该事件冒泡到document。

阻止冒泡

stopPropagation函数

btn.addEventListener('click',function(ev){
  ev.stopPropagation();
  console.log('阻止冒泡')
}, false)

事件委托(事件代理)

原理

如果有多个DOM节点需要监听事件的情况下,给每个DOM绑定监听函数,会极大的影响页面的性能,因为我们通过事件委托来进行优化,事件委托利用的就是冒泡的原理。

<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
<script>
  var li_list = document.getElementsByTagName('li')
  for(let index = 0;index<li_list.length;index++){
    li_list[index].addEventListener('click', function(ev){
      console.log(ev.currentTarget.innerHTML)
    })
  }
</script>

正常情况我们给每一个li都会绑定一个事件,但是如果这时候li是动态渲染的,数据又特别大的时候,每次渲染后(有新增的情况)我们还需要重新来绑定,又繁琐又耗性能;这时候我们可以将绑定事件委托到li的父级元素,即ul。

var ul_dom = document.getElementsByTagName('ul')
ul_dom[0].addEventListener('click', function(ev){ 
  console.log(ev.target.innerHTML)
})

target和currentTarget区别:

  • target返回触发事件的元素,不一定是绑定事件的元素
  • currentTarget返回的是绑定事件的元素

优点

  • 提高性能: 每一个函数都会占用内存空间,只需添加一个事件处理程序代理所有事件,所占用的内存空间更少。
  • 动态监听: 使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以一样具有和其他元素一样的事件。

以上就是详解JavaScript 事件流的详细内容,更多关于JavaScript 事件流的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript while语句和do while语句的区别分析
Dec 08 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
Oct 29 Javascript
原生javascript实现匀速运动动画效果
Feb 26 Javascript
BootStrap学习笔记之nav导航栏和面包屑导航
Jan 03 Javascript
AngularJS实现的根据数量与单价计算总价功能示例
Dec 26 Javascript
vue 开发一个按钮组件的示例代码
Mar 27 Javascript
vue2.0 资源文件assets和static的区别详解
Apr 08 Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
May 01 Javascript
vue加载完成后的回调函数方法
Sep 07 Javascript
浅谈webpack SplitChunksPlugin实用指南
Sep 17 Javascript
微信小程序解析富文本过程详解
Jul 13 Javascript
避坑之 JavaScript 中的toFixed()和正则表达式
Apr 19 Javascript
JavaScript判断数据类型有几种方法及区别介绍
Sep 02 #Javascript
jQuery中getJSON跨域原理的深入讲解
Sep 02 #jQuery
JavaScript交换变量常用4种方法解析
Sep 02 #Javascript
Vue-cli打包后部署到子目录下的路径问题说明
Sep 02 #Javascript
Jquery $.map使用方法实例详解
Sep 01 #jQuery
JQuery基于FormData异步提交数据文件
Sep 01 #jQuery
vue实现路由懒加载的3种方法示例
Sep 01 #Javascript
You might like
PHP判断IP并转跳到相应城市分站的方法
2015/03/25 PHP
javascript Xml增删改查(IE下)操作实现代码
2009/01/30 Javascript
JavaScript的parseInt 进制问题
2009/05/07 Javascript
jQuery Ajax使用 全解析
2010/12/15 Javascript
js与jquery获取父元素,删除子元素的两种不同方法
2014/01/09 Javascript
js使用for循环查询数组中是否存在某个值
2014/08/12 Javascript
javascript类型系统 Array对象学习笔记
2016/01/09 Javascript
基于Javascript实现返回顶部按钮
2016/02/29 Javascript
JavaScript实现数据类型的相互转换
2016/03/06 Javascript
jQuery.form插件的使用及跨域异步上传文件
2016/04/27 Javascript
简单谈谈Vue 模板各类数据绑定
2016/09/25 Javascript
浅谈ng-zorro使用心得
2018/12/03 Javascript
详解wepy开发小程序踩过的坑(小结)
2019/05/22 Javascript
Angular.JS读取数据库数据调用完整实例
2019/07/02 Javascript
layui-table表复选框勾选的所有行数据获取的例子
2019/09/13 Javascript
Vue+Element-UI实现上传图片并压缩
2019/11/26 Javascript
[01:02:48]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 LGD vs OG
2018/04/02 DOTA
[41:08]TNC vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
使用python实现baidu hi自动登录的代码
2013/02/10 Python
用Python的Flask框架结合MySQL写一个内存监控程序
2015/11/07 Python
Python实现的多线程同步与互斥锁功能示例
2017/11/30 Python
基于pycharm导入模块显示不存在的解决方法
2018/10/13 Python
Ubuntu下Python2与Python3的共存问题
2018/10/31 Python
Django异步任务之Celery的基本使用
2019/03/23 Python
Django 路由层URLconf的实现
2019/12/30 Python
Django+Uwsgi+Nginx如何实现生产环境部署
2020/07/31 Python
详解Python中的编码问题(encoding与decode、str与bytes)
2020/09/30 Python
Python3.7安装PyQt5 运行配置Pycharm的详细教程
2020/10/15 Python
CSS3制作炫酷带方向感应的鼠标滑过图片3D动画
2016/03/16 HTML / CSS
Huda Beauty官方商店:化妆和美容产品
2020/09/05 全球购物
官僚主义现象查摆问题整改措施
2014/10/04 职场文书
银行授权委托书样本
2014/10/13 职场文书
高三教师工作总结2015
2015/07/21 职场文书
门卫管理制度范本
2015/08/05 职场文书
html5中sharedWorker实现多页面通信的示例代码
2021/05/07 Javascript
怎么禁用Win11输入法 最新Win11输入法关闭教程
2022/08/05 数码科技