js事件浅析
js中关于DOM的操作很多,因此js事件机制也就尤为重要。
事件绑定形式:
一. 内联形式
耦合度高,不利于维护
<button onclick="alert('你点击了这个按钮');">点击这个按钮</button>
二. 属性绑定(DOM0级事件)
只能绑定一个函数
button.onclick = function() {};
三. 事件监听函数(DOM2级事件)
element.addEventListener(<event-name>, <callback>, <use-capture>);
element.removeEventListener(<event-name>, <callback>, <use-capture>);
element.attachEvent(event, callback)(IE11以后用addEventLisener);
element.detachEvent(event, callback)(IE11以后用addEventLisener);
事件代理
在父元素上绑定事件,监听子元素的事件。主要用于子元素是新建元素或者子元素个数很多的情况下。这种方法可以提高性能,同时避免提前绑定元素事件而导致新建元素的事件没有生效的结果。
<ul> <li>11111111111111111111</li> </ul>
document.addEventListener('click', function (e) {
console.log('document currentTarget: ' + e.currentTarget.nodeName);
console.log('document target: ' + e.target.nodeName);
if (e.target.nodeName === 'LI') {
console.log('dom delegate: ' + e.eventPhase);
}
console.log(this);
}, true);
事件触发顺序
- Event Capturing(事件捕获): Netscape
- Event Bubbling(事件冒泡): IE
这两种方式确定了事件执行的前后顺序,只不过后来W3C对DOM2的事件模型给出了一个规范:首先进入事件捕获阶段->达到元素后->进入事件冒泡阶段。
可以通过event.eventPhase查看事件触发阶段:
eventPhase (number): 这个属性的数字表示当前事件触发在什么阶段。
- 0: none
- 1: 捕获
- 2: 目标
- 3: 冒泡
1. DOM0
在元素处于目标时触发该事件。
2. DOM2
当addEventListener的最后参数为false时,是在冒泡阶段触发。如果是true的话是在捕获阶段出发。attachEvent始终是冒泡阶段触发。
允许捕获机制的事件流触发顺序:
事件流的触发顺序是首先从document元素开始,触发绑定在document上的捕获事件,依次向下,直到目标元素上。然后触发绑定在目标元素上的事件。最后依次向上,直到触发document元素上绑定的捕获事件。分别可以对于捕获阶段,处于目标阶段,冒泡阶段,捕获过程和冒泡过程并不包含目标元素阶段。

尝试下面的函数:
<ul>
<li>11111111111111111111</li>
</ul>
<script>
document.querySelector('li').addEventListener('click', function (e) {
console.log('False currentTarget: ' + e.currentTarget.nodeName);
console.log('False target: ' + e.target.nodeName);
console.log(e.eventPhase);
console.log(this);
}, false);
document.querySelector('li').addEventListener('click', function (e) {
console.log('True currentTarget: ' + e.currentTarget.nodeName);
console.log('True target: ' + e.target.nodeName);
console.log(e.eventPhase);
console.log(this);
}, true); document.querySelector('ul').addEventListener('click', function (e) {
console.log('ul false currentTarget: ' + e.currentTarget.nodeName);
console.log('ul false target: ' + e.target.nodeName);
console.log(e.eventPhase);
console.log(this);
}, false);
document.querySelector('ul').addEventListener('click', function (e) {
console.log('ul true currentTarget: ' + e.currentTarget.nodeName);
console.log('ul true target: ' + e.target.nodeName);
console.log(e.eventPhase);
console.log(this);
}, true);
document.querySelector('li').onclick = function (e) {
console.log('Onclick currentTarget: ' + e.currentTarget.nodeName);
console.log('Onclick target: ' + e.target.nodeName);
console.log(e.eventPhase);
console.log(this);
}; </script>
BeCareful: 可以看到,当点击li的时候,前两个绑定的事件是按照顺序来执行的,并没有先执行捕获事件然后执行冒泡事件,而是按照绑定顺序执行的。且event.eventPhase的值为2。
原因是:浏览器针对于事件的触发机制是,执行每个阶段会先设置在哪个阶段,然后在node的事件数组里执行相应阶段的事件。如果处于目标阶段是不区分捕获或者冒泡阶段的,直接按照注册顺序执行当前事件数组里的函数。event.eventPhase是在调用这些方法的时候设置的。而true和false是在注册的时候开发者传入的。

注释里面的那段话的意思就是,在目标阶段会触发捕获和冒泡事件的监听函数,因此,它会按照注册顺序执行,跟我们平时理解的顺序并不一样。


自定义事件
DOM3级还定义了自定义事件,自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件。要创建的自定义事件可以由createEvent("CustomEvent");
返回的对象有一个initCustomEvent()方法接收如下四个参数。
1)type:字符串,触发的事件类型,自定义。例如 “keyDown”,“selectedChange”;
2)bubble(布尔值):标示事件是否应该冒泡;
3)cancelable(布尔值):标示事件是否可以取消;
4)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);
}
事件对象及行为
1. 事件目标
event = event || window.event;
target = event.target || event.srcElement;
event.target 和event.currentTarget的区别:前者是触发事件的最终目标,后者是绑定事件时的目标。
借用事件代理的例子:
<div class="btn" onclick="console.log('onclick')">
<span>sss</span>
</div>
document.querySelector('.btn').addEventListener('click', function (e) {
console.log('False currentTarget: ' + e.currentTarget.nodeName);
console.log('False target: ' + e.target.nodeName);
console.log(e.eventPhase);
console.log(this);
}, false);

2. 取消默认行为 & 阻止事件冒泡
DOM:
event.preventDefault();
event.stopPropagation();
IE8以下:
event.returnValue = false;
event.cancelBubble = true;
return false方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://cdn.bootcss.com/jquery/1.11.0/jquery.js"></script>
</head>
<body> <div onclick="alert('Outer clicked')">
Outer Div<br><br>
<a id="inner" href="http://www.google.com" onclick="return false;">Google</a>
<script>
document.getElementById('inner').addEventListener('click', function(e){
alert(e.type);
e.stopPropagation();
return false;
}, false);
document.getElementById('inner').onclick = function(e){
alert(e.type);
e.stopPropagation();
return false;
}; $('#inner').click(function (e) {
return false;
});
</script>
</div>
</body>
</html>
在没有使用jquery的情况下,return false这种方式只有在DOM0的方式时可以相当于阻止默认行为的方法,DOM2级事件是不起任何效果的。
如果在jquery环境,return false相当于阻止默认行为和冒泡行为的方法,因为jquery本身的定义。
参考资料:
js事件浅析的更多相关文章
- Node.js事件的正确使用方法
前言 事件驱动的编程变得流行之前,在程序内部进行通信的标准方法非常简单:如果一个组件想要向另外一个发送消息,只是显式地调用了那个组件上的方法.但是在 react 中用的却是事件驱动而不是调用. 事件的 ...
- dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来
dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...
- 什么是JS事件冒泡?
什么是JS事件冒泡?: 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理 程序或者事件返回true,那么 ...
- js事件技巧方法整合
window.resizeTo(800,600); //js设置浏览器窗口尺寸 window.open (function(){ resizeTo(640,480);//设置浏览器窗口尺寸 moveT ...
- js 事件大全
Js事件大全一般事件 事件 浏览器支持 描述onClick IE3|N2|O3 鼠标点击事件,多用在某个对象控制的范围内的鼠标点击onDblClick IE4|N4|O 鼠标双击事件onMouseDo ...
- 原生JS事件绑定方法以及jQuery绑定事件方法bind、live、on、delegate的区别
一.原生JS事件绑定方法: 1.通过HTML属性进行事件处理函数的绑定如: <a href="#" onclick="f()"> 2.通过JavaS ...
- JS事件
JS事件: 声明:为了事件对象event跨浏览器兼容: var oEvent==ev||event; 所以在下面用到 event 的地方都用 oEvent 代替 1)doucument的 ...
- 原生js事件和jquery事件的执行顺序问题
场景:近日,写前端页面时候,在针对输入框input操作时,用到了jquery的插件,插件中使用了jquery的focus()和blur()方法.但是同时,又需要在插件之外再针对输入框的获取焦点和失去焦 ...
- 特殊js事件
1:点击enter事件 $(document).keypress(function(e) { // 回车键事件 if(e.which == 13) { submitForm(); } }); 2:JQ ...
随机推荐
- Maven Plugins常用配置
官方文档:http://maven.apache.org/plugins/index.html# 这里主要介绍compiler插件的配置.http://maven.apache.org/plugins ...
- 【Win 10应用开发】SplitView控件
SplitView控件用于呈现分隔视图,简单地说,就是把一个视图分割为两部分,Content属性所表示的为主要视图,而Pane属性设置的视图则可以隐藏,可以折叠和展开. 估计文字是不太容易介绍这个控件 ...
- 前端MVC框架Backbone 1.1.0源码分析系列
Backbone.js 是一个在JavaScript环境下的 模型-视图-控制器 (MVC) 框架.任何接触较大规模项目的开发人员一定会苦恼于各种琐碎的事件回调逻辑.以及金字塔般的代码.而且,在传统的 ...
- 【原创】数据挖掘案例——ReliefF和K-means算法的医学应用
数据挖掘方法的提出,让人们有能力最终认识数据的真正价值,即蕴藏在数据中的信息和知识.数据挖掘 (DataMiriing),指的是从大型数据库或数据仓库中提取人们感兴趣的知识,这些知识是隐含的.事先未知 ...
- 小菜学习Winform(六)剪切板和拖放复制
前言 在做winform项目的时候有时候会用到复制粘贴,在.net中提供了Clipboard类来操作剪切板,我们来看下. clipbrd.exe clipbrd是系统剪切板程序,但是在vista及以上 ...
- WebStorm按Tab建快速生成代码模块
WS中,比如调试每次都要写的console.log(xxx);每次都要敲一遍,还有if模块,for循环模块,难道没有快捷键,可以生成代码模块吗,答案是“有”. 操作步骤如下(汉化版WS): 1.Alt ...
- JS详细入门教程(上)
首先,我们看一下DOM级别和兼容性: 之前好像在某本上看到说DOM有0级,实际上,DOM0级标准是不存在的.DOM有1.2.3三个级别.DOM1级由两个模块组成(DOM Core和DOM HTML), ...
- 相克军_Oracle体系_随堂笔记003-体系概述
1.进程结构图 对Oracle生产库来讲,服务器进程(可以简单理解是前台进程)的数量远远大于后台进程.因为一个用户进程对应了一个服务器进程. 而且后台进程一般出问题几率不大,所以学习重点也是服务器进程 ...
- PostgreSql+PostGIS和uDig的安装
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 总体来说,这两款开源软件均是很好安装的,一般按照提示一步一步 ...
- 【集合框架】JDK1.8源码分析之Comparable && Comparator(九)
一.前言 在Java集合框架里面,各种集合的操作很大程度上都离不开Comparable和Comparator,虽然它们与集合没有显示的关系,但是它们只有在集合里面的时候才能发挥最大的威力.下面是开始我 ...