详解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 相关文章推荐
juqery 学习之五 文档处理 插入
Feb 11 Javascript
js定义对象或数组直接量时各浏览器对多余逗号的处理(json)
Mar 05 Javascript
按下Enter焦点移至下一个控件的实现js代码
Dec 11 Javascript
jQuery的DOM操作之删除节点示例
Jan 03 Javascript
js实现三张图(文)片一起切换的banner焦点图
Aug 25 Javascript
JavaScript动态插入CSS的方法
Dec 10 Javascript
JavaScript实现ASC转汉字及汉字转ASC的方法
Jan 23 Javascript
JS中Json数据的处理和解析JSON数据的方法详解
Jun 29 Javascript
详解AngularJS中ng-src指令的使用
Sep 07 Javascript
js时间查询插件使用详解
Apr 07 Javascript
JS实现生成由字母与数字组合的随机字符串功能详解
May 25 Javascript
vue router-link 默认a标签去除下划线的实现
Nov 06 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 sprintf() 函数的应用(定义和用法)
2012/06/29 PHP
php命名空间学习详解
2014/02/27 PHP
php中json_encode处理gbk与gb2312中文乱码问题的解决方法
2014/07/10 PHP
PHP严重致命错误处理:php Fatal error: Cannot redeclare class or function
2017/02/05 PHP
JS弹出对话框返回值代码(asp.net后台)
2010/12/28 Javascript
js使用removeChild方法动态删除div元素
2014/08/01 Javascript
Javascript中call与apply的学习笔记
2014/09/22 Javascript
jquery实现勾选复选框触发事件给input赋值
2015/02/01 Javascript
jQuery实现的图文高亮滚动切换特效实例
2015/08/10 Javascript
canvas实现钟表效果
2017/02/13 Javascript
对vuejs的v-for遍历、v-bind动态改变值、v-if进行判断的实例讲解
2018/08/27 Javascript
Javascript实现时间倒计时功能
2018/11/17 Javascript
[08:06]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant 选手采访
2021/03/11 DOTA
Python实现图片尺寸缩放脚本
2018/03/10 Python
windows7 32、64位下python爬虫框架scrapy环境的搭建方法
2018/11/29 Python
如何使用Python进行OCR识别图片中的文字
2019/04/01 Python
Python Process多进程实现过程
2019/10/22 Python
基于python及pytorch中乘法的使用详解
2019/12/27 Python
通过实例了解Python str()和repr()的区别
2020/01/17 Python
关于tf.reverse_sequence()简述
2020/01/20 Python
python查询MySQL将数据写入Excel
2020/10/29 Python
BCBG官网:BCBGMAXAZRIA
2017/12/29 全球购物
python re模块和正则表达式
2021/03/24 Python
物理研修随笔感言
2014/02/14 职场文书
班班通校本培训方案
2014/03/12 职场文书
学校募捐倡议书
2014/05/14 职场文书
舞蹈专业求职信
2014/06/13 职场文书
作风建设年度心得体会
2014/10/29 职场文书
项目经理岗位职责
2015/01/31 职场文书
党员个人总结范文
2015/02/14 职场文书
初中重阳节活动总结
2015/05/05 职场文书
英雄儿女观后感
2015/06/09 职场文书
《陶罐和铁罐》教学反思
2016/03/03 职场文书
超市啤酒狂欢夜策划方案范文!
2019/07/03 职场文书
Java使用Unsafe类的示例详解
2021/09/25 Java/Android
Win11 22H2 2022怎么更新? 获得Win1122H22022版本升级技巧
2022/09/23 数码科技