详解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
Oct 31 Javascript
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
Mar 04 Javascript
javascript获取select的当前值示例代码(兼容IE/Firefox/Opera/Chrome)
Dec 17 Javascript
js身份证判断方法支持15位和18位
Mar 18 Javascript
js常用数组操作方法简明总结
Jun 20 Javascript
javascript十六进制及二进制转化的方法
May 06 Javascript
jquery代码实现多选、不同分享功能
Jul 31 Javascript
javascript实现状态栏中文字动态显示的方法
Oct 20 Javascript
从零开始学习Node.js系列教程六:EventEmitter发送和接收事件的方法示例
Apr 13 Javascript
Vue的移动端多图上传插件vue-easy-uploader的示例代码
Nov 27 Javascript
去掉vue 中的代码规范检测两种方法(Eslint验证)
Mar 21 Javascript
原生Js 实现的简单无缝滚动轮播图的示例代码
May 10 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
在Windows系统上安装PHP运行环境文字教程
2010/07/19 PHP
php插入排序法实现数组排序实例
2015/02/16 PHP
php curl中gzip的压缩性能测试实例分析
2016/11/08 PHP
Zend Framework入门教程之Zend_Mail用法示例
2016/12/08 PHP
PHP使用POP3读取邮箱接收邮件的示例代码
2020/07/08 PHP
JQuery读取XML文件数据并显示的实现代码
2009/12/16 Javascript
node.js中Socket.IO的进阶使用技巧
2014/11/04 Javascript
Jquery 分页插件之Jquery Pagination
2015/08/25 Javascript
Vue数据驱动模拟实现3
2017/01/11 Javascript
Node.js发送HTTP客户端请求并显示响应结果的方法示例
2017/04/12 Javascript
vue-cli如何快速构建vue项目
2017/04/26 Javascript
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
2017/06/14 Javascript
JavaScript 上传文件(psd,压缩包等),图片,视频的实现方法
2017/06/19 Javascript
探索webpack模块及webpack3新特性
2017/09/18 Javascript
前端html中jQuery实现对文本的搜索功能并把搜索相关内容显示出来
2017/11/14 jQuery
ReactNative中使用Redux架构总结
2017/12/15 Javascript
详解VueJs中的V-bind指令
2018/05/03 Javascript
一起写一个即插即用的Vue Loading插件实现
2019/10/31 Javascript
js利用拖放实现添加删除
2020/08/27 Javascript
vue集成openlayers加载geojson并实现点击弹窗教程
2020/09/24 Javascript
Python实现一个Git日志统计分析的小工具
2017/12/14 Python
用Python进行简单图像识别(验证码)
2018/01/19 Python
pandas DataFrame实现几列数据合并成为新的一列方法
2018/06/08 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
2020/01/08 Python
基于python爬取有道翻译过程图解
2020/03/31 Python
使用HTML5原生对话框元素并轻松创建模态框组件
2019/03/06 HTML / CSS
幼儿园毕业园长感言
2014/02/24 职场文书
营销总监岗位职责范本
2014/02/26 职场文书
学习两会精神心得范文
2014/03/17 职场文书
应届大专毕业生自我鉴定
2014/04/08 职场文书
校庆标语集锦
2014/06/25 职场文书
离职证明范本(5篇)
2014/09/19 职场文书
银行职员工作失误检讨书
2014/10/14 职场文书
高中政治教学反思
2016/02/23 职场文书
关于Nginx中虚拟主机的一些冷门知识小结
2022/03/03 Servers
开发者首先否认《遗弃》被取消的传言
2022/04/11 其他游戏