详解JavaScript 事件流

事件

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

事件流

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

事件流类别

事件冒泡

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

事件捕获

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

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

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

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

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

DOM事件级别

分为四个级别

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 事件流的资料请关注我们其它相关文章!

(0)

相关推荐

  • 学习JavaScript事件流和事件处理程序

    本文全篇介绍了JavaScript事件流和事件处理程序,分享给大家供大家参考,具体内容如下 一.事件流 事件流描述的是从页面中接收事件的顺序.IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获流. 二.事件冒泡 即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点.如: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT

  • JS事件流与事件处理程序实例分析

    本文实例讲述了JS事件流与事件处理程序.分享给大家供大家参考,具体如下: 1.事件流:从页面中接收事件的顺序 1.1 IE :事件冒泡流 1.2 Netscape :事件捕获 1.3 DOM事件流 :事件捕获阶段--事件目标阶段--事件冒泡阶段 DOM2级事件规定 :捕获阶段不会涉及目标事件. 2.事件处理程序 事件 :用户或者浏览器自身执行的 某种动作 事件处理程序 :响应某个事件的 函数 . 2.1 HTML事件处理程序 用一个与该事件处理程序同名的HTML特性来指定. 2.1.1包含要执行

  • Javascript 事件流和事件绑定

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

  • JavaScript 事件流、事件处理程序及事件对象总结

    JS与HTML之间的交互通过事件实现.事件就是文档或浏览器窗口中发生的一些特定的交互瞬间.可以使用监听器(或处理程序)来预定事件,以便事件发生时执行相应的代码.这种在传统软件工程中被称为观察员模式,支持页面的行为与页面的外观之间的松散耦合.本文将介绍JS事件相关的基础知识. 一.事件流 事件流描述的是从页面中接受事件的顺序. 事件冒泡 事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的结点(文档).以下面HTML页面为例,如果你点击了页面中的按钮,那么"

  • 详解JavaScript中的事件流和事件处理程序

    事件流:分两种,IE的是 事件冒泡流 ,事件开始时从最具体的元素接收,逐级向上传播到较为不具体的节点(Element -> Document).与之相反的是 Netscape 的 事件捕获流 . DOM2级事件规定事件流包括三个阶段:事件捕获阶段.处于目标阶段和事件冒泡阶段. 大多数情况下都是将事件处理程序添加到事件流的冒泡阶段.一个 EventUtil 的栗子: var EventUtil = { addHandler: function(element, type, handler){ if

  • JavaScript事件学习小结(一)事件流

    相关阅读: JavaScript事件学习小结(五)js中事件类型之鼠标事件 http://www.jb51.net/article/86259.htm JavaScript事件学习小结(一)事件流 http://www.jb51.net/article/86261.htm javaScript事件学习小结(四)event的公共成员(属性和方法) http://www.jb51.net/article/86262.htm JavaScript事件学习小结(二)js事件处理程序 http://www

  • 深入理解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.首先我们来了解几个概念,"事件","事件流","事件名称","事件处理函数/事件监听函数,也许是"老生常谈",知道的朋友可以越过. 事件: 事件是用户自身或浏览器进行的特定行为.如:用户点击 也就是常用的click事件 事件流:多个事件 按一定顺序触发 形成了事件流 事件名称:如上面所讲的click就是事件名 事件处理函数/事件监听函数(Dom的叫法)就是 事件触发后的处理函数,如obj.onclick=fn;函

  • JS对象与JSON互转换、New Function()、 forEach()、DOM事件流等js开发基础小结

    1.数据类型:JavaScript定义的数据类型有字符串.数字.布尔.数组.对象.Null.Undefined,但typeof有区分可判别的数据分类是number.string.boolean.object(null / array).function和undefined.undefined 这个值表示变量不含有值,null 可以用来清空变量 let a = 100; typeof a;//number a = undefined; typeof a;//undefined a = null;

  • 详解JavaScript 事件流

    事件 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道这些事件是在什么时候进行调用的,就需要了解一下"事件流"的概念. 事件流 事件流描述的就是从页面中接收事件的顺序.而早期的IE和Netscape提出了完全相反的事件流概念,IE事件流是事件冒泡,而Netscape的事件流就是事件捕获. 事件流类别 事件冒泡 即从下至上,从目标触发的元素逐级向上传播,直到win

  • 详解javascript事件冒泡

    事件是javascript中的核心内容之一,在对事件的应用中不可避免的要涉及到一个重要的概念,那就是事件冒泡,在介绍事件冒泡之前,先介绍一下另一个重要的概念事件流: 一.什么是事件流: 文档对象模型(DOM)是一个树形结构,可以形象的用下图表示. 如果一个html元素触发事件,那么这个事件就会在DOM树中的触发节点和根节点之间按照一定的顺序传播,所有经过的节点都会接收到被触发的事件,这个传播过程被称之为事件流.按照事件的传播顺序,可以将其分为两类,一种是事件冒泡,一种是事件捕获,这里就涉及到本章

  • 详解javascript事件绑定使用方法

    由于html是从上至下加载的,通常我们如果在head部分引入javascript文件,那么我们都会在javascript的开头添加window.onload事件,防止在文档问加载完成时进行DOM操作所出现的错误.如果有多个javascript文件,那么极有可能出现多个window.onload事件,但是最后起作用的只有一个,这时候就需要使用事件绑定来解决这个问题了. IE方式 attachEvent(事件名称, 函数),绑定事件处理函数 detachEvent(事件名称, 函数),解除绑定 DO

  • 详解JavaScript事件循环机制

    众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. There a

  • 详解javascript实现瀑布流绝对式布局

    瀑布流也应该算是流行几年了吧.首先是由Pinterest掀起的浪潮,然后国内设计如雨后春笋般,冒出很多瀑布流的例子,比如,蘑菇街,Mark之(不过最近涉黄,好像被喝茶了),还有淘宝的 "哇哦". 这些都是很棒的例子, 今天我们就聊一聊瀑布流. 一.绝对式布局: JS实现原理 其实瀑布式主要的难点就在于,如果将图片整齐的排列在对应的列下,以及什么时候开始刷新加载图片. 而图片整齐的排列的主要逻辑和算法即,先获取容器内可以放多少列,然后,通过计算,存放第一列的高度,再遍历剩下(除第一列的元

  • 详解Javascript 中的 class、构造函数、工厂函数

    到了ES6时代,我们创建对象的手段又增加了,在不同的场景下我们可以选择不同的方法来建立.现在就主要有三种方法来构建对象,class关键字,构造函数,工厂函数.他们都是创建对象的手段,但是却又有不同的地方,平时开发时,也需要针对这不同来选择. 首先我们来看一下,这三种方法是怎样的 // class 关键字,ES6新特性 class ClassCar { drive () { console.log('Vroom!'); } } const car1 = new ClassCar(); consol

  • 详解JavaScript匿名函数和闭包

    概述 在JavaScript前端开发中,函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure).也就是说,闭包可以让你从内部函数访问外部函数作用域.在JavaScript,函数在每次创建时生成闭包.匿名函数和闭包可以放在一起学习,可以加深理解.本文主要通过一些简单的小例子,简述匿名函数和闭包的常见用法,仅供学习分享使用,如有不足之处,还请指正. 普通函数 普通函数由fucntion关键字,函数名,() 和一对{} 组成,如下所示: function

  • 详解JavaScript 的执行机制

    一.关于javascript javascript是一门单线程语言,在最新的HTML5中提出了Web Worker,但javascript是单线程这一核心仍未改变. 为什么js是单线程的语言?因为最初的js是用来在浏览器验证表单操纵DOM元素的.如果js是多线程的话,两个线程同时对一个DOM进行了相互冲突的操作,那么浏览器的解析是无法执行的. Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行.在主线程运行的同

  • 详解JavaScript执行模型

    JavaScript执行模型 引言 JavaScript是一个单线程(Single-threaded)异步(Asynchronous)非阻塞(Non-blocking)并发(Concurrent)语言,这些语言效果通过一个调用栈(Call Stack).一个事件循环(Event Loop).一个回调队列(Callback Queue)有些时候也叫任务队列(Task Queue)与跟运行环境相关的API组成. 概念 调用栈 Call Stack 调用栈是一个LIFO后进先出数据结构的函数运行栈,它

  • 详解JavaScript 异步编程

    异步的概念 异步(Asynchronous, async)是与同步(Synchronous, sync)相对的概念. 在我们学习的传统单线程编程中,程序的运行是同步的(同步不意味着所有步骤同时运行,而是指步骤在一个控制流序列中按顺序执行).而异步的概念则是不保证同步的概念,也就是说,一个异步过程的执行将不再与原有的序列有顺序关系. 简单来理解就是:同步按你的代码顺序执行,异步不按照代码顺序执行,异步的执行效果更高: 以上是关于异步的概念的解释,接下来我们通俗地解释一下异步:异步就是从主线程发射一

随机推荐