事件高级
元素注册事件的方式
给元素添加事件,称为注册事件或绑定事件
传统方式
- 利用on开头的事件 如onclick
- <标签 οnclick=“alert(hi~)”></标签>
- 事件源.onclick = function(){}
特点: 注册事件的唯一性。同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖之前的
方法监听注册
-
addEventListener() (IE9以上)
- W3C标准推荐方式
- eventTarget.addEventListener(type,listener[,useCapture])
- type:事件类型字符串,如click mouseover
- listener:事件处理函数,事件发生时,会调用监听函数
- useCapture:可选参数,布尔值。默认false
-
attachEvent()(IE9以下)
btns[2].attachEvent(‘onclick’, function() {
alert(‘This is a IE9- way’);
})
特点: 同一个元素同一个事件可注册多个监听器
*注册事件兼容性问题解决方案
兼容原则:先处理大多数浏览器,再处理特殊浏览器
var btns = document.querySelectorAll('button');
//1.传统方式注册事件
btns[0].onclick = function() {
alert('This is a traditional way');
}
btns[0].onclick = function() {
alert('"This is a traditional way" is covered')
}
//2.方法监听注册事件
btns[1].addEventListener('click', function() {
alert('This is a IE9+ way');
})
btns[1].addEventListener('click', function() {
alert('"This is a IE9+ way" is not covered');
})
//3.IE9- attachEvent
btns[2].attachEvent('onclick', function() {
alert('This is a IE9- way');
})
//注册事件兼容性问题解决方案 兼容原则:先处理大多数浏览器,再处理特殊浏览器
function addEventListener(element, eventName, fn) {
if (element.addEventListener) {
element.addEventListener(eventName, fn);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = fn;
}
}
删除事件的两种方式
传统注册事件
事件源.绑定事件 = null
方法监听注册事件
- eventTarget.removeEventListener(type, listenser[, useCapture]);
- eventTarget.detachEvent(eventNameWithOn, callback);
* 删除事件兼容性问题解决方案
//1.传统方式删除事件
btns[0].onclick = function() {
alert('"This is a traditional way" is covered');
btns[0].onclick = null;
}
//2.removeEventListener()
btns[1].addEventListener('click', clickFn);
function clickFn() {
alert('only one');
btns[1].removeEventListener('click', clickFn);
}
//3.detachEventListener()
btns[2].attachEvent('onclick', clickFn2);
function clickFn2() {
alert('only one');
btns[2].detachEvent('onclick', clickFn2);
}
//删除事件兼容性解决方案
function removeEventListener(element, eventName, fn) {
if (element.removeEventListener) {
element.removeEventListener(eventName, fn);
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn)
} else {
element['on' + eventName] = null;
}
}
DOM事件流的三个阶段
定义
事件流描述的是从页面接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
步骤
- 捕获阶段 :由DOM最顶层节点开始,逐级向下传播到最具体的元素接收的过程
- 当前目标阶段
- 冒泡阶段:事件由最具体的元素接收,逐级向上传播到DOM最顶层节点的过程
注:
- JS代码只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent 只能得到冒泡阶段
- addEventListener(type, listener[, useCapture])第三个参数是true,表示在事件捕获阶段调用事件处理程序;如果是false,表示在事件冒泡阶段调用事件处理程序
- 实际开发中更关注事件冒泡
- onblur onfocus onmouseenter onmouseleave 没有冒泡
//dom事件流
var first_div = document.querySelector('.first-div');
var second_div = document.querySelector('.second-div');
//捕获阶段
// first_div.addEventListener('click', fn1, true)
// second_div.addEventListener('click', fn2, true);
// function fn1() {
// alert("I'm first div");
// }
// function fn2() {
// alert("I'm second div");
// }
//冒泡阶段
first_div.addEventListener('click', fn1, false)
second_div.addEventListener('click', fn2); //默认是false
function fn1() {
alert("I'm first div");
}
function fn2() {
alert("I'm second div");
}
事件对象
含义
事件源.绑定事件 = function(event){}
- event就是一个事件对象,在侦听函数里,当作形参看
- 事件对象,有了事件才会存在,是系统自动创建的,不需要人为传参
- 事件对象是事件的一系列相关数据的集合,是跟事件相关的。如:鼠标点击事件就包含鼠标的相关信息;键盘事件就包含键盘的信息。
- 事件对象可自定义命名,如:event、 e、 evt
- 兼容性问题:IE9- 通过
event = event || window.event; //兼容性写法
常见属性和方法
- 返回事件对象
- e.target 返回触发事件的对象(标准)
- this 返回绑定事件的事件对象
- e.currentTarget 返回绑定事件的事件对象
- e.srcElement 返回触发事件的对象(非标准,IE9-)
first_div.addEventListener('click', fn1, false)
second_div.addEventListener('click', fn2); //默认是false
function fn1(event) {
alert("I'm first div");
event = event || window.event; //兼容性写法
//当点击second_div时
console.log(event.target); //指向触发事件的对象,返回 second_div
console.log(this); //指向绑定事件的事件源,返回first_div
console.log(event.currentTarget); //指向绑定事件
}
function fn2() {
alert("I'm second div");
}
document.addEventListener('click', function() {
alert("I'm document");
})
- 阻止默认行为(事件)
- e.returnValue 该属性阻止默认事件(默认行为)(非标准,IE9-),如:不让链接跳转
- e.preventDefault() 该属性阻止默认事件(默认行为)(标准),如:不让链接跳转
- return false 没有兼容性问题,也可以阻止默认行为
//阻止默认行为(事件),让链接不跳转,或提交按钮不提交
var a = document.querySelector('a');
var form = document.querySelector('form');
var input = document.querySelector('input');
a.addEventListener('click', f1);
function f1(e) {
e.preventDefault(); //dom标准写法 函数
e.returnValue; //IE9- 方法
}
a.onclick = function() {
return false; //没有兼容性问题,也可以阻止默认行为。缺点:return 后面的代不执行了,只限于传统的注册方式
}
- e.type 返回事件的类型,如:click、mouseover
- 阻止冒泡
- e.stopPropagation() 阻止冒泡(标准)
- e.cancelBubble 该属性阻止冒泡(非标准,IE9-)
封装阻止冒泡的兼容性函数
first_div.addEventListener('click', fn1, false)
second_div.addEventListener('click', fn2); //默认是false
second_div.addEventListener('mouseover', fn2);
second_div.addEventListener('mouseout', fn2);
function fn1(event) {
alert("I'm first div");
if (event && e.stopPropagation) {
event.stopPropagation();
} else {
window.event.cancelBubble = true;
}
}
function fn2(e) {
alert("I'm first_div");
}
document.addEventListener('click', function() {
alert("I'm document");
})
事件委托的原理
事件委托也称为事件代理,在jQuery里称为事件委派。
原理
不是给每个字节点单独设置事件监听器,而是将其设置在其父节点上,然后利用冒泡原理影响每个子节点
作用
只操作一次DOM,提高了程序的性能
//当存在多个子节点都需要注册同一类型的事件时,通过事件委托,委托给父节点,就能做到操作一次DOM,影响所有子节点
<ul>
<li>知否知否</li>
<li>应是绿肥红瘦</li>
</ul>
//事件委托
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
alert(e.target.innerHTML);
e.stopPropagation();
})
常用的鼠标事件
- 禁止鼠标右键菜单
<p>你看看能不能点开右键菜单</p>
//禁止右键菜单
var p = document.querySelector('p');
p.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
- 禁止鼠标选中
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
鼠标事件对象
- e.clientX 返回鼠标相对于浏览器窗口可视区的X坐标
- e.clientY 返回鼠标相对于浏览器窗口可视区的Y坐标
- e.pageX 返回鼠标相对于文档页面的X坐标 (IE9+)
- e.pageY 返回鼠标相对于文档页面的Y坐标 (IE9+)
- e.screenX 返回鼠标相对于电脑屏幕的X坐标
- e.screenY 返回鼠标相对于电脑屏幕的Y坐标
常用的键盘事件
- onkeyup 某个键盘按键被松开时触发
- onkeydown 某个键盘按键被按下时触发
- onkeypress 某个键盘按键被按下时触发,但不识别功能键,如ctrl shift 箭头等
注:
执行顺序:onkeydown onkeypress onkeyup
如果使用addEventListener,不需要加on
// 1. onkeyup 某个键盘按键被松开时触发
document.onkeyup = function() {
console.log("I'm up");
}
// 2. onkeydown 某个键盘按键被按下时触发
document.onkeydown = function() {
console.log("I'm down");
}
// 3. onkeypress 某个键盘按键被按下时触发, 但不识别功能键, 如ctrl shift 箭头等
document.onkeypress = function() {
console.log("I'm press");
}
键盘事件对象
keyCode 返回该键的ASCII
注:
keyup keydown 不区分字母大小写
keypress 区分字母大小写