JavaScript DOM

DOM 事件模型

DOM(Document Object Model 文件对象模型)

DOM将用例如XML、HTML等标记语言写成的结构化文档当作一颗树,该树上的节点也便是文档内的节点。简单来讲,DOM是一组API,可使用户经过任何实现了DOM API的语言操纵任何知足DOM标准的文档。javascript

DOM 0级事件模式

<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>Hello World</title> </head> <body> <div class='test'>Test</div> <script> let div = document.getElementsByClassName('test')[0]; div.onclick = function(){ console.log('click'); } </script> </body> </html> 

 

 


<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>Hello World</title> </head> <body> <div class='test' onclick='console.log("click)'>Test</div> </body> </html> 

 

上述代码都为类名为test的div绑定了一个click事件发生时触发的方法。这种为DOM元素设置事件函数的方法即是DOM 0级事件模型中规定的。除此以外,DOM 0级事件模型还不容许为一个元素的同一事件绑定多个处理方法。若绑定了多个,则最后一个函数覆盖以前的。html

<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>Hello World</title> </head> <body> <div class='test'>Test</div> <script> let div = document.getElementsByClassName('test')[0]; div.onclick = function(){ console.log('click'); } //若是用户点击Test则会在控制台输出click again而不是click。 div.onclick = function(){ console.log('click again'); } </script> </body> </html> 

 

 

DOM 2级事件模型

DOM 2级事件模型为咱们提供两个方法分别用来添加和移除事件处理方法。前端

  • addEventListener()
  • removeEventListener()

这两个方法的前两个参数是相同的,分别是事件名和事件处理函数(remove方法没法移除匿名函数)。而add方法则多出了一个参数,若传入true,则事件处理方法在事件捕获阶段被调用,反之则在事件冒泡阶段被调用。java


<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>Hello World</title> </head> <body> <div class='test'>Test</div> <script> let div = document.getElementsByClassName('test')[0]; div.addEventListener('click', function(){ console.log('click'); }, false); div.addEventListener('click', function(){ console.log('click again'); }, true); </script> </body> </html> 

 

 

与DOM 0级不一样,DOM 2级事件模型容许你为同个元素的同个事件添加多个事件处理函数,在触发时间时将会按照文档顺序被前后调用。浏览器

事件的冒泡与捕获

image

<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>Hello World</title> </head> <body> <div id='one'> <div id='two'> <div id='three'> <p>Test</p> </div> </div> </div> <script> let div1 = document.getElementById('one'); let div2 = document.getElementById('two'); let div3 = document.getElementById('three'); div1.addEventListenr('click' , function(event){ console.log('one'); }, false); div2.addEventListenr('click' , function(event){ console.log('two'); }, false); div3.addEventListenr('click' , function(event){ console.log('three'); }, false); div1.addEventListenr('click' , function(event){ console.log('one'); }, true); div2.addEventListenr('click' , function(event){ console.log('two'); }, true); div3.addEventListenr('click' , function(event){ console.log('three'); }, true); </script> </body> </html>





 

DOM 事件流

说实话,如今不管是什么框架你都离不开操做DOM啊,毕竟这是你展现的最基本元素,就像人的细胞。想起了dom事件流原理,好多人不明白,只知道click mouseout等实用场景,真要理解和更进一步的前端是要必须:理论+实践 并行的。

固然,DOM事件所囊括的知识较为庞杂,因此本文专一与本身学习时所碰到的难点,DOM事件流。markdown

流的概念,在现今的JavaScript中随处可见。好比说React中的单向数据流,Node中的流,又或是今天本文所讲的DOM事件流。都是流的一种生动体现。至于流的具体概念,咱们采用下文的解释:网络

用术语说流是对输入输出设备的抽象。以程序的角度说,流是具备方向的数据。框架

事件流之事件冒泡与事件捕获dom

在浏览器发展的过程当中,开发团队遇到了一个问题。那就是页面中的哪一部分拥有特定的事件?函数

能够想象画在一张纸上的一组同心圆,若是你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上全部的圆。放到实际页面中就是,你点击一个按钮,事实上你还同时点击了按钮全部的父元素。

开发团队的问题就在于,当点击按钮时,是按钮最外层的父元素先收到事件并执行,仍是具体元素先收到事件并执行?因此这儿引入了事件流的概念。

事件流所描述的就是从页面中接受事件的顺序。

由于有两种观点,因此事件流也有两种,分别是事件冒泡和事件捕获。现行的主流是事件冒泡。

事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),而后逐级传播到较为不具体的节点。

举个栗子,就很容易明白了。

而后,咱们给 button 和它的父元素,加入点击事件。

效果如图所示:

在代码所示的页面中,若是点击了button,那么这个点击事件会按以下的顺序传播(Chrome浏览器):

1. button

2. body

3. document

4. window

也就是说,click事件首先在 <button> 元素上发生,而后逐级向上传播。这就是事件冒泡。

事件捕获的概念,与事件冒泡正好相反。它认为当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件。好比说刚才的demo,若是是事件捕获的话,事件发生顺序会是这样的:

1. window

2. document

3. body

4. button

固然,因为时代更迭,事件冒泡方式更胜一筹。因此放心的使用事件冒泡,有特殊须要再使用事件捕获便可。

DOM事件流

DOM事件流包括三个阶段:

1. 事件捕获阶段

2. 处于目标阶段

3. 事件冒泡阶段

如图所示(图片源于网络,若侵权请告知):

事件捕获阶段

也就是说,当事件发生时,首先发生的是事件捕获,为父元素截获事件提供了机会。

例如,我把上面的Demo中,window点击事件更改成使用事件捕获模式。(addEventListener最后一个参数, 为true则表明使用事件捕获模式 ,false则表示使用事件冒泡模式。不理解的能够去学习一下addEventListener函数的使用)


此时,点击button的效果是这样的。

能够看到,点击事件先被父元素截获了,且该函数只在事件捕获阶段起做用。

处于目标与事件冒泡阶段

事件到了具体元素时,在具体元素上发生,而且被当作冒泡阶段的一部分。随后,冒泡阶段发生,事件开始冒泡。

阻止事件冒泡

事件冒泡过程,是能够被阻止的。防止事件冒泡而带来没必要要的错误和困扰。

这个方法就是: stopPropagation() 

咱们对 button 的click事件作一些改造。


点击后,效果以下图:

不难看出,事件在到达具体元素后,中止了冒泡。但不影响父元素的事件捕获。

小结

事件流:描述的就是从页面中接受事件的顺序。

分有事件冒泡与事件捕获两种。

DOM事件流的三个阶段:

1. 事件捕获阶段

2. 处于目标阶段

3. 事件冒泡阶段

相关文章
相关标签/搜索