原生Javascript之事件
来源:互联网 发布:电脑键盘记录软件 编辑:程序博客网 时间:2024/06/14 21:07
事件
就是和浏览器产生交互效果的,事件触发和函数一起使用,当触发事件的时候,调用相应的事件去处理接下来的事情。
DOM0
级事件
直接在
dom对象
上注册事件名称,所有浏览器都支持。
document.getElementById('div1').onclick=function(e){ // 触发事件之后的操作}
事件触发会默认传入一个参数e
:事件对象
;通过这个事件对象,可以获取到触发这个事件的dom元素
,点击的坐标值,等一些主要的信息。当然事件的触发也可以这样写:
document.getElementById('div1')['onclick']=function(e){// 触发事件后的操作}
这上面的两种事件的触发,其实也就是js对象
身上属性的两种访问方式,也就是说:
- DOM0
级事件是元素对象的私有属性;
- 同一个元素对象,同一个事件行为,只能绑定一次,多次绑定,后面的会覆盖前面的;
- DOM0
级事件发生在事件流的冒泡阶段
DOM0
级事件中的this
一般下面这种写法的时候,当事件触发的时候,事件中的this
就是指向触发该事件的dom
元素对象
<script>var oDiv=document.getElementById('div1');oDiv.onclick=function(e){ // 触发事件之后的操作alert(this.id); // div1}// 要想解除div身上的点击事件,直接在后面注册点击事件并且设置为nulloDiv.onclick=null; </script>
当把事件写在html代码
里面的时候,虽然也遵守事件覆盖的原则,但不会传入event事件对象
,相当于动态调用函数,this
指向的是window
,而不是事件触发者:dom元素
:
<div id='div1' class='div1' onclick='exec();'></div>
DOM2
级事件
支持元素绑定多个事件
addEventListener()
- 注册事件
this
指向被绑定事件的这个元素- 三个参数:事件行为(去掉前边的on),处理函数回调(默认传入event对象,this指向触发的元素节点),捕获/冒泡(true/false)
- 给同一个元素,同一个行为绑定多次同一个方法,实际上只执行一次
- 对应同一个元素来说,是按照事件绑定的先后顺序执行的
var btn=document.getElementById('div');btn.addEventListener('click',function(e){ console.log(this); // btn },false)
removeEventListener()
- 移除事件
IE8及其以下版本浏览器,
attachEvent()
- 对于同一个元素,绑定多个事件,事件执行的顺序不是按照绑定的顺序执行
- 事件中的
this
默认指向window
- 给同一个元素,同一个行为绑定多次同一个方法,执行是多次的
detachEvent()
阻止冒泡
e.stopPropagation()
标准浏览器e.cancelBubble=true
低级IE浏览器- 兼容性写法
通过e.stopPropagation来判断是标准浏览器还是低级IE浏览器e.stopPropagation? e.stopPropagation(): e.cancelBubble=true;
阻止默认事件
e.preventDefault
标准浏览器e.returnValue=false
低级IE浏览器
通过e.preventDefault来判断是标准浏览器还是低级IE浏览器 e.preventDefault?e.preventDefault():e.returnValue=false;
事件流
定义
文档对象模型DOM
的结构是一个树状,当一个元素产生一个事件时,该事件会在元素节点与跟节点按特定的顺序传播,路径所经过的节点都会收到该事件,这个过程称为事件流
类型
- 事件捕获
- 从上往下
- 由最顶层的元素到下面最精确的元素(事件产生的元素)
- 事件冒泡
- 从下往上
- 事件从子节点(事件产生的元素)一直向上传递到根节点
- 事件发生的元素传递到与元素有确定从属关系的其他元素上面,直到传递找不到确定的元素上面结束
- 冒泡的好处:事件委托
DOM
标准同时支持上述两种事件类型,但是捕获事件
先发生。两种事件流都会触发DOM
中的所有对象,在document对象
开始,也在其中结束。但也有标准的浏览器会将事件延续到window对象
。
- 捕获事件要比冒泡事件先触发
<div id='div1'> <div id='div2'></div></div>var btn=document.getElementById('div1'); // 冒泡 btn.addEventListener('click',function(e){ console.log('冒泡') },false); // 捕获事件 btn.addEventListener('click',function(e){ console.log('捕获') },true);
当我们点击里面的div的时候,是先打印捕获,在打印冒泡;但是当我们先点击外面的div的时候,是先打印的冒泡,在打印的是捕获;为什么?
根据事件流触发的顺序图,可以知道,当我们点击里面的div
的时候,根据下面的事件流传递的过程
原理知道,是先发生捕获事件在发生冒泡事件;当点击的是外面的div
,并且事件绑定在点击元素上面,其触发的顺序是按照绑定的顺序触发的
外层div和内层div同时注册了捕获事件,那么点击内层div时,外层div的事件一定是先触发的;外层div和内层div都是注册的冒泡事件,点击内层div时,一定是内层div事件先执行,原理相同。
首先是捕获事件传递,接着是冒泡事件传递;要是一个事件处理函数同时注册了捕获和冒泡事件,则会在dom事件模型
中调用两次。标准的DOM事件模型
(特有):文本节点也会触发事件,但是IE不会
事件流传递过程
如果为一个超链接添加了click
事件监听器,那么当该链接被点击时该事件监听器就会被执行。但如果把该事件监听器指派给了包含该链接的p
元素或者位于DOM
树顶端的document
节点,那么点击该链接也同样会触发该事件监听器。这是因为事件不仅仅对触发的目标元素产生影响,它们还会对沿着DOM
结构的所有元素产生影响。
W3C事件模型中明确地指出了事件流转送的原理。可以分为3个阶段。
- 事件捕捉(Capturing)阶段
- 事件将沿着DOM树向下转送,目标节点的每一个祖先节点,直至目标节点。
- 例如,若用户单击了一个超链接,则该单击事件将从document节点转送到html元素,body元素以及包含该链接的p元素。
- 在此过程中,浏览器都会检测针对该事件的捕捉事件监听器,并且运行这件事件监听器。
- 实际事件发生的目标元素在捕获阶段是不会接收事件的。
- `目标(target)阶段
- 浏览器在查找到已经指定给目标事件的事件监听器之后,就会运行该事件监听器。目标节点就是触发事件的DOM节点。
- 例如,如果用户单击一个超链接,那么该链接就是目标节点(此时的目标节点实际上是超链接内的文本节点)。
- 事件发生的目标元素发生事件并且处理事件。
- 冒泡(Bubbling)阶段
- 事件将沿着DOM树向上转送,再次逐个访问目标元素的祖先节点到document节点。
- 该过程中的每一步,浏览器都将检测那些不是捕捉事件监听器的事件监听器,并执行它们。
并非所有的事件都会经过冒泡阶段的,所有的事件都要经过捕捉阶段和目标阶段,但是有些事件会跳过冒泡阶段。例如,让元素获得输入焦点的focus事件以及失去输入焦点的blur事件就都不会冒泡。
事件冒泡(代理\委托)
利用到事件的冒泡和目标元素,把事件处理器添加到父元素上,等待子元素事件冒泡,并且父元素能够通过
target
(IE为srcElement
),事件源
,来判断是哪一个子元素,从而进行处理
<body><ul id="color-list"><li>red</li><li>orange</li><li>yellow</li><li>green</li><li>blue</li><li>indigo</li><li>purple</li></ul><script>(function(){ var colorList=document.getElementById("color-list"); colorList.addEventListener('click',showColor,false); function showColor(e) { e=e||window.event;// 获取事件目标元素 var targetElement=e.target||e.srcElement; if(targetElement.nodeName.toLowerCase()==="li"){ alert(targetElement.innerHTML); } }})();</script></body>
好处
- 将多个事件处理器减少到一个,因为事件处理器要驻留内存,这样就提高了性能。想象如果有一个100行的表格,对比传统的为每个单元格绑定事件处理器的方式和事件代理(即table上添加一个事件处理器),不难得出结论,事件代理确实避免了一些潜在的风险,提高了性能。
- DOM更新无需重新绑定事件处理器,因为事件代理对不同子元素可采用不同处理方法。如果新增其他子元素(a,span,div等),直接修改事件代理的事件处理函数即可,不需要重新绑定处理器,不需要再次循环遍历。
- 原生Javascript之事件
- 原生JavaScript事件详解
- JavaScript原生事件机制
- 原生JavaScript事件详解
- javascript模拟原生事件
- 原生JavaScript事件详解
- 原生JavaScript事件详解
- 原生JavaScript事件详解
- 原生javascript 添加事件 代码
- javascript原生的事件扩展
- JavaScript自定事件-原生代码
- React—Native开发之原生模块向JavaScript发送事件
- 原生Javascript之拖曳效果
- javascript给元素定义自定义事件(非html原生事件)
- jQuery事件绑定和JavaScript原生事件绑定的区别
- JavaScript事件之鼠标事件
- 原生JavaScript Demo之星星评分
- JavaScript之AJAX:原生ajax入门
- CSR8675的DSP学习笔记——离线调试与仿真
- while与break、continue、return以及goto的使用
- git+gerrit+jenkins经典组合之安装使用
- 用JVISUALVM远程监控JAVA程序的性能
- php fatal error-Allowed memory size
- 原生Javascript之事件
- 前端工具_ps_01
- 数据结构与算法专题之线性表——链表(二)双向链表
- 169. Majority Element
- 菜鸟心历之路(1)
- C++多态理解及多态对象模型探索
- vector模板类的C++实现
- 关于动态链库与动态链接库的心得
- 欢迎使用CSDN-markdown编辑器