▊ 注册事件的两种方式
传统注册方式(前一阶段主要使用的):
- 通常利用
on
开头的时间 - 注册事件的唯一性:同一个元素同一个事件只能设置一个处理函数,后边会覆盖前面的
方法监听注册方式
- 利用
addEventListener()
方法 - 同一个元素同一个事件可以注册多个监听器(function函数),依次执行
▊ 删除事件(解绑事件)
// [传统方法对应:]
var div = document.querySelectorAll('div');
div.onclick = function() {
alert('loli');
div.onclick = null; // 注意是null,不是none ! ! !
}
// [方法监听方式对应:]
div.addEventListener('click', fun); // 因为要移除,就不能写匿名函数了
function fun() {
alert('loli');
div.removeEventListener('click', fun); // removeEventListener有两个必要参数:绑定的事件;函数名(不加括号);最后一个参数默认false,控制事件流
}
▊ DOM事件流
事件流是从页面接收事件的顺序:事件会在元素节点之间按照特定的顺序传播,这个传播过程称为DOM事件流
DOM事件流分为三个阶段:捕获阶段、当前目标阶段、冒泡阶段
注:
- JS代码只能执行捕获或冒泡其中的一个阶段
onclick
等只能得到冒泡阶段- addEventListener第三个参数如果是true,则在捕获阶段调用事件处理程序;如果是false,则在冒泡阶段调用事件处理程序
- 有些事件时没有冒泡的,比如
onblur
,onfocus
,onmouseenter
,onmouseleave
▊ 事件对象
div.addEventListener('click', function(event) {
console.log(event);
})
// 1.类似一个传递信息的形参,写在监听函数的括号内
// 2.系统自动创建
// 3.事件相关的信息数据集合都放在这个对象里,比如鼠标的位置、键盘的位置
e.target |
返回触发事件的对象 |
e.type |
返回事件的类型(比如click, mouseover,不带on) |
e.preventDefault() |
阻止默认事件(默认行为) |
e.stopPropagation() |
阻止冒泡 |
ul.addEventListener('click', function(e) {
console.log(e.target);
})
// target返回的是触发事件的对象(li);this返回的是绑定事件的对象(ul)
// 通俗地讲,target返回的是实际被点击的那个对象;this返回的是代码中声明的被绑定的对象
a.addEventListener('click', function(e) {
e.preventDefault(); // 阻止默认行为(链接不跳转,提交不提交)(类似于禁用按钮disabled的作用)
})
son.addEventListener('click', function(e) {
alert('This is son.');
e.stopPropagation(); // 阻止向上冒泡
})
▊ 事件委托(代理)
Q:事件委托的原理?(★☆★)
A:不是给每个子节点单独设置监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
举个例子:比如ul-li结构,之前在设置监听器时,是通过循环注册,给每个li都设置了一个监听器;
而使用了事件委托后,即给只设置一个监听器在ul上,只操作了一次DOM,提高了性能
▊ 常用的鼠标事件
之前提到的有:onclick, onmouseover, onmouseout, onfocus, onblur, onmouseup, onmousedown, onmousemove
下面再补充两个有趣的——可以禁止用户的复制粘贴:
document.addEventListener('contextmenu', function(e) { // 禁止鼠标右键
e.preventDefault();
})
document.addEventListener('selectstart', function(e) { // 禁止选中的开始
e.preventDefault();
})
另一个有趣的效果:鼠标DIY
var pic = document.querySelector('img'); // img一定先在css设置【绝对定位】
document.addEventListener('mousemove', function(e) { // 核心就是用mousemove获取xy坐标值,赋给left和top
var x = e.pageX;
var y = e.pageY;
pic.style.left = x + 'px';
pic.style.top = y + 'px';
// 上面两行是雷区!值一定一定是字符串,直接写 pic.style.left = x 是错误的
})
补充几个鼠标事件对象(MouseEvent) 的常用属性:
e.clientX, e.clientY | 相对于可视区的X,Y坐标 |
e.pageX, e.pageY | 相对于整个文档页面的X,Y坐标 |
e.screenX, e.screenY | 相对于电脑屏幕的X,Y坐标 |
▊ 常用的键盘事件
onkeyup
, onkeydown
, onkeypress
关于keydown和keypress的解惑:
- 与keydown相比,keypress不识别ctrl shift 方向等功能键
- 注意触发顺序:keydown → keypress
- 我们一般都会使用keyup,这有两个好处:一来keydown和keypress按住时会被一直触发,而keyup显然只在抬起时触发一次;二来,我们在往文本框输入时,keydown和keypress在文字写入之前就被触发了,而keyup在文字已经写入后触发,我们需求恰恰通常是处理输入的文字(★☆★很致命的知识点)
补充几个键盘事件对象(MouseEvent) 的常用属性(其实常用的就一个):
e.keyCode | keyup和keydown不区分大小写(保持小写);keypress区分大小写 |
☀ Loli & JS
♫ Suki