如何绑定事件
elem.onxxx = function(event) {}
- 兼容性很好,但是一个元素的同一个事件上只能绑定一个处理程序
- 基本等同于写在HTML行间上
obj.addEventListener(type, fn, false)
- IE9以下不兼容,可以为一个事件绑定多个处理程序
obj.attachEvent('on'+type, fn)
- IE独有,一个事件同样可以绑定多个处理程序
事件处理程序中
elem.onxxx = function(event) {}
- 程序中
this
指向是dom
元素本身
- 程序中
obj.addEventListener(type, fn, false)
- 程序中
this
指向是dom
元素本身
- 程序中
obj.attachEvent('on'+type, fn)
- 程序中
this
指向是window
- 程序中
封装addEvent(elem, type, handle)函数
function addEvent(elem, type, handle) {
if (elem.addEventListener) {
elem.addEventListener(type, handle, false);
} else if (elem.attachEvent) {
elem.attachEvent('on'+type, function () {
handle.call(elem);
});
} else {
elem['on'+type] = handle;
}
}
解除事件处理函数
-
elem.onclick = false/""/null;
-
elem.removeEventListener(type, fn, false);
-
elem.detachEvent('on'+type, fn);
注意:若绑定匿名函数,则无法解除
事件处理模型——事件冒泡、事件捕获
- 事件冒泡:
- 结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡至父元素。(自底向上)
- 事件捕获:
- 结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自底向上)
- 触发:
addEventListener(type, fn, true); // 第三个参数为 true
- IE上没有事件捕获
-
触发顺序:先捕获,后冒泡。
// 即一个对象上同时绑定了事件冒泡和事件捕获 div.addEventListener('click', fn1, false); div.addEventListener('click', fn2, true); // 先执行fn2,后执行fn1。
-
focus
,change
,blur
,submit
,reset
,select
等事件不冒泡。 -
取消冒泡:
-
W3C标准
event.stopPropagation();
不支持IE9以下版本 -
IE独有:
event.cancelBubble = true;
-
封装取消冒泡的函数
function stopBubble (event) { if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } }
-
阻止默认事件:
- 默认事件——表单提交、a标签跳转、右键菜单等
-
return false;
- 以对象属性等方式注册等事件猜生效
-
event.preventDefault();
- W3C标准,IE9以下不兼容
-
event.returnValue = false;
- 兼容IE
-
封装阻止默认事件等函数
function cancelHandler (event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } }
事件对象
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
var oDIv = document.getElementById('box');
oDiv.onclick = function(event){
// 这里的参数event就是储存了该事件状态的对象
// 拿到event,我们可以更好的监听事件
}
- 一些基本属性
属性和方法 描述 srcElement 对于生成事件的 Window 对象、Document 对象或 Element 对象的引用。 target 返回触发此事件的元素(事件的目标节点)。 currentTarget 返回其事件监听器触发该事件的元素。 type 返回当前 Event 对象表示的事件的名称。 preventDefault() 通知浏览器不要执行与事件关联的默认动作。 stopPropagation() 取消冒泡。 cancelBubble 如果事件句柄想阻止事件传播到包容对象,必须把该属性设为 true。
// 一些关于event的兼容写法
//获得event对象兼容性写法
event || (event = window.event);
//获得target兼容型写法
event.target||event.srcElement
//阻止浏览器默认行为兼容性写法
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
//阻止冒泡写法
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
事件委托
把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。
事件代理的原理是DOM元素的事件冒泡。
即:子元素点击会触发父元素的点击事件,所以,将事件绑定在父元素上,其所有子元素皆可触发该事件。
- 可以大量节省内存占用,减少事件注册,
- 可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
- 通过事件对象的
target
属性可以判断触发事件的具体元素
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
// 一般做法
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
item1.onclick = function() {
location.href = "xxx";
};
item2.onclick = function() {
document.title = "事件委托";
};
item3.onclick = function() {
alert("hi");
};
// 但若是ul中有成千上万个li需要动态的添加并绑定事件的话,则代码十分冗余,且有很多监听事件,浪费内存
// 此时使用事件委托,只需注册一个事件监听,再通过target判断子元素执行其事件
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
document.addEventListener("click", function (event) {
var target = event.target;
switch (target.id) {
case "doSomething":
document.title = "事件委托";
break;
case "goSomewhere":
location.href = "xxx";
break;
case "sayHi": alert("hi");
break;
}
})