详解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 相关文章推荐
基于jQuery的弹出警告对话框美化插件(警告,确认和提示)
Jun 10 Javascript
用js代码改变单选框选中状态的简单实例
Dec 18 Javascript
jQuery复制表单元素附源码分享效果演示
Sep 30 Javascript
在JavaScript中模拟类(class)及类的继承关系
May 20 Javascript
用headjs来管理和加载js 提高网站加载速度
Nov 29 Javascript
简单实现Vue的observer和watcher
Dec 21 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
Feb 19 Javascript
Angular父组件调用子组件的方法
Apr 02 Javascript
微信小程序云开发之模拟后台增删改查
May 16 Javascript
vue+elementUI动态生成面包屑导航教程
Nov 04 Javascript
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
Aug 14 Javascript
js用正则表达式筛选年月日的实例方法
Jan 04 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
国内咖啡文化
2021/03/03 咖啡文化
简单的过滤字符串中的HTML标记
2006/12/25 PHP
php入门学习知识点六 PHP文件的读写操作代码
2011/07/14 PHP
国外PHP程序员的13个好习惯小结
2012/02/20 PHP
php中get_magic_quotes_gpc()函数说明
2017/02/06 PHP
解决出现SoapFault (looks like we got no XML document)的问题
2017/06/24 PHP
记录Yii2框架开发微信公众号遇到的问题及解决方法
2018/07/20 PHP
php实现大文件断点续传下载实例代码
2019/10/01 PHP
PHP 扩展Memcached命令用法实例总结
2020/06/04 PHP
Prototype Hash对象 学习
2009/07/19 Javascript
如何实现修改密码时密码框显示保存到cookie的密码
2013/12/10 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
2014/05/05 Javascript
JavaScript实现的购物车效果可以运用在好多地方
2014/05/09 Javascript
js 去除字符串第一位逗号的方法
2014/06/07 Javascript
jquery获得同源iframe内body下标签的值的方法
2014/09/25 Javascript
js拼接html字符串的注意事项
2016/10/13 Javascript
懒加载实现的分页&amp;&amp;网站footer自适应
2016/12/21 Javascript
JavaScript实现审核流程状态的动态显示进度条
2017/03/15 Javascript
深入理解angular2启动项目步骤
2017/07/15 Javascript
Bootstrap + AngularJS 实现简单的数据过滤字符查找功能
2017/07/27 Javascript
ES6中新增的Object.assign()方法详解
2017/09/22 Javascript
js实现购物车功能
2018/06/12 Javascript
vue实现几秒后跳转新页面代码
2020/09/09 Javascript
使用Python进行新浪微博的mid和url互相转换实例(10进制和62进制互算)
2014/04/25 Python
Python-Tkinter Text输入内容在界面显示的实例
2019/07/12 Python
python对一个数向上取整的实例方法
2020/06/18 Python
CSS实现的一闪而过的图片闪光效果
2014/04/23 HTML / CSS
新西兰最大的在线设计师眼镜店:SmartBuyGlasses新西兰
2017/10/20 全球购物
欧洲领先的电子和电信零售商和服务提供商:Currys PC World Business
2017/12/05 全球购物
殡葬服务心得体会
2014/09/11 职场文书
三八妇女节标语
2014/10/09 职场文书
习近平在党的群众路线教育实践活动总结大会上的讲话
2014/10/21 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
英语投诉信范文
2015/07/03 职场文书
PostgreSQL基于pgrouting的路径规划处理方法
2022/04/18 PostgreSQL
SQL Server2019安装的详细步骤实战记录(亲测可用)
2022/06/10 SQL Server