一、JS中的DOM事件模型
JS中有两种事件模型:
- DOM 0级事件模型 (几乎所有浏览器都支持)
- DOm 2级事件模型(现代浏览器几乎都支持,IE8之前的不支持)
(一)DOM 0级事件模型
有两种形式:
//第一种:html标签中添加事件
<input type="button" onclick="doSomething(...)"/>
//第二种:dom对象绑定事件
input.onclick=function(){
...}
缺点:只能添加一个相同的事件,之后添加的会覆盖前面的。
input.onclick=function(){
alert(1);} //被覆盖了,不会执行
input.onclick=function(){
alert(2);} //之后的dom点击事件会覆盖前面的。
(二)事件冒泡
点击子元素,其父元素的事件处理模型也都被执行了。
//点击<p>标签
<body>
<div id="div1">
<div id="div1-1">
<div id="div1-1-1">
<div id="div1-1-1-1">
<p id="p1">
事件冒泡测试
</p>
</div>
</div>
</div>
</div>
<script type="text/javascript">
document.getElementById('p1').onclick=function(event){
console.log('p1');};
document.getElementById('div1').onclick=function(event){
console.log('div1');};
document.getElementById('div1-1').onclick=function(event){
console.log('div1-1');};
document.getElementById('div1-1-1').onclick=function(event){
console.log('div1-1-1');};
document.getElementById('div1-1-1-1').onclick=function(event){
console.log('div1-1-1-1');};
//结果为从内到外以此触发事件,vue中也会遇到
//p1
//div1-1-1-1
//div1-1-1
//div1-1
//div1
</script>
</body>
取消事件冒泡
- event.stopPropagation();
- event.cancelBubble = true;
(三)DOM 2级事件模型
DOM 2级事件模型弥补了DOM 0级事件缺陷,可以绑定多个相同事件。
同时也拥有事件捕获和事件冒泡的功能(事件捕获:从祖先元素捕获到子元素,和冒泡相反)
事件捕获:从祖先元素向下传播
事假冒泡:从子元素向上传播
DOM2注册事件处理函数:
addEventListenter(eventType,listener,useCapture)
- eventType:事件类型(click、focus、blur)不带on
- listener:事件处理函数,可以是匿名函数
- useCapture:默认值是false,只冒泡不捕获;true只捕获不冒泡(捕获很少用)。
attachEvent(eventName,handler)(IE)
老的IE浏览器使用attachEvent添加事件处理函数
- eventName:事件名称(需要加上on)
- handler:事件处理函数
var event = event || window.event;
var target = event.target || event.srcElement;
使用原生JS绑定DOM事件需要兼容各种浏览器的写法
var EventsUtility = {
addEvent: function (element, type, callback) {
if (typeof addEventListener !== 'undefined') { //DOM 2级事件
element.addEventListener(type, callback, false);
} else if (typeof attachEvent !== 'undefined') {
element.attachEvent('on' + type, callback); //DOM 2级事件,兼容IE
} else { //DOM 0级事件,兼容低版本浏览器
element['on' + type] = callback;
}
},
removeEvent: function (element, type, callback) {
if (typeof removeEventListener !== 'undefined') { //DOM 2级事件
element.removeEventListener(type, callback, false);
} else if (typeof detachEvent !== 'undefined') {
element.detachEvent('on' + type, callback); //DOM 2级事件,兼容IE
} else { //DOM 0级事件,兼容低版本浏览器
element['on' + type] = null;
}
},
}
二、jQuery事件模型
特点:
- 提供统一的事件处理方法
- 内部采用了DOM2级事件模型,允许添加多个事件处理函数
- 使用标准事件名称,不带on
- event事件实例作为事件处理函数的第一个参数
- 标准化了事件常用属性,解决了兼容性问题 比如target
- 提供了统一的事件取消和阻止默认行为的方法
(一)添加DOM事件处理
.on(eventType[,selector][,data][,handler]) //推荐使用,其他的方法不推荐
$('XXX').on(eventType[,select][,data],function(event){
//event.target得到的是事件发生元素
})
- eventType 事件类型,多个事件可以用空格分隔
- selector表示一个选择器 指定事件注册的后代(用于事件委托)
- data 表示传递的数据,可以在函数中使用,通过event.data获取
- 表示事件处理函数
- 可以使用链式语法添加多个事件
事件委托
如果要为大量的元素绑定事件的话,为每个元素都绑定一个事件效率会很低。使用事件委托可以提高效率。
事件委托,利用事件冒泡的原理,把子元素的相同的事件委托给父元素,子元素上发生的某个事件会从父元素哪里得到具体的事件处理程序。
- 此时event.target是发生事件的子元素
- 上面的selector可以指定哪些子元素需要委托此事件
- 新添加的符合selector的子元素默认就委托了此事件
//新闻列表数量太多,每一个都绑定事件效率低,而且还会有新加
<body>
<div class="new">
<p class="new-li p1">新闻段落1</p>
<p class="new-li p2">新闻段落2</p>
<p class="new-li p3">新闻段落3</p>
<p class="new-li p4">新闻段落4</p>
<p class=