本篇为 JavaScript 系列笔记第六篇,将陆续更新后续内容。参考:黑马程序员JavaScript核心教程,前端基础教程
系列笔记:
JavaScript(一)—— 初识JavaScript / 注释 / 输入输出语句 / 变量 / 数据类型
JavaScript(二)—— 运算符 / 流程控制 / 数组
JavaScript(三)—— 函数 / 作用域 / 预解析 / 对象
JavaScript(四)—— 内置对象 / 简单数据类型与复杂类型
JavaScript(五)—— Web APIs 简介 / JavaScript 必须掌握的 DOM 操作
一、注册事件
给元素添加事件,称为注册事件或绑定事件。主要分为两种方式:传统注册方式和方法监听注册方式
- 传统注册方式
如利用 on 开头的事件 onclick
。但是,传统注册方式有一个特点:同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会层叠前面的。
1. <button onclick="alert('hi')"></button>
2. btn.onclick = function(){}
- 方法监听注册方式
这是 W3C 标准所推荐的方式,利用方法 addEventListener()
,则同一个元素同一个事件可以注册多个监听器,按注册顺序依次执行。
1. EventTarget.addEventListener(type, listener[, useCapture])
此方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。其中,有三个参数
- type:事件类型字符串 ,如 click、mouseover(没有 on)
- listener:事件处理函数,事件发送时调用此函数
- useCapture:可选参数,布尔值,默认 fasle
2. attachEvent()
attachEvent()
是 IE 浏览器独有的,兼容性问题很大,MDN上已经查询不到此方法,此处不再做介绍
二、删除事件
- 传统删除事件方式
eventTarget.onclick = null;
- 方法监听删除方式
eventTarget.removeEventListener(type, listener[, useCapture])
注意:这里是参数是 fn
(函数变量),而不是 fn()
,是指将函数绑定到事件中
三、DOM 事件流
DOM 结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为 DOM 事件流。
- DOM 事件流 分 3 个阶段
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
- 注意
- JS 代码中只能执行捕获或冒泡其中的一个阶段
onclick
和attachEvent
只能得到冒泡阶段addEventListener(type, listener[, useCapture])
第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(默认),表示在事件冒泡阶段调用事件处理程序
- 事件捕获
此示例中注册事件第三个为 true
,处于捕获阶段,执行顺序为:document —— html —— body —— father —— son
- 事件冒泡
实际开发中我们很少使用事件捕获,而是更关注事件冒泡。但是有些事件是没有冒泡的,如 onblur、onfocus、onmouseenter、onmouseleave
此示例中注册事件第三个为 false
,处于冒泡阶段,执行顺序为:son —— father —— body —— html —— document
四、事件对象
1. eventTarget.onclick = function (event) {}
2. eventTarget.addEventListener('click', function (event) {})
event 就是事件对象,也可写做 e 或 evt
event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
- 注意
- event 是形参,系统设定为事件对象,无须传递实参
- IE 6~8 存在兼容性问题,必须通过
window.event
获取;标准浏览器定义形参e
即可。可以通过e = e || window.event;
进行兼容性处理
- 常见的属性和方法
-
e.target
返回触发事件的对象,this
返回的是绑定事件的对象
在本例中,我们点击 abc 触发了该事件,因此e.target
指向 li,而 ul 绑定了此事件,所以this
指向 ul -
返回事件类型
e.type
-
阻止默认行为(事件)
e.preventDefault()
让链接不跳转,或者让提条按钮不提交
return false
缺点是后面代码不再执行,而且只限于传统注册方式
五、阻止事件冒泡
- 阻止事件冒泡的两种方式
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到 DOM 最顶层节点
- 标准写法:利用事件对象里面的
stopPropagation()
方法
- 兼容性解决方案(了解)
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
六、事件委托(代理、委派)
事件委托也称为事件代理,在 jQuery 里面称为事件委派
- 事件委托的原理
不是每个子节点单独设置事件监听器,而是将事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
- 事件委托的作用
- 支持为同一个 DOM 元素注册多个同类型事件
- 可将事件分成事件捕获和事件冒泡机制
七、常用的鼠标事件
contextmenu
和selectstart
-
禁止鼠标右键菜单
contextmenu
主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单 -
禁止鼠标选中(
selectstart
开始选中)
- 鼠标事件对象
event 对象代表事件的状态,跟事件相关的一系列信息的结合。现阶段我们主要是用 鼠标事件对象 MouseEvent 和键盘事件对象 KeyboardEvent
client
返回在可视区的坐标,与滚动条无关page
返回相对于文档页面的位置,需要考虑滚动条,重点记忆screen
返回相对于电脑屏幕的位置,使用的较少
- 案例:跟随鼠标的天使
<img src="images/angel.gif" alt="">
<script>
var img = document.querySelector('img');
document.addEventListener('mousemove', function (e) {
var x = e.pageX;
var y = e.pageY;
console.log('x坐标是' + x, 'y坐标是' + y);
img.style.top = y - 40 + 'px';
img.style.left = x - 40 + 'px';
})
</script>
- 采取绝对定位,不占位置
- x、y 坐标作为图片的 left、top 值,注意加单位 px
八、常用键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发,但是它不识别功能键,比如 ctrl shift 箭头 |
三个事件的执行先后顺序:onkeydown
- onkeypress
- onkeyup
- 键盘事件对象
键盘事件对象中的 keyCode
属性可以得到相应键的 ASCII 代码值
keyup
和keydown
事件不区分字母大小写,a 和 A 得到的都是 65keypress
区分大小写,a :97 、A : 65
注意:MDN 中以及将此属性废弃,尽量不要使用
- 案例:模拟京东按键输入内容
当我们按下 s 键,光标就定位到搜索框
<input type="text">
<script>
// 搜索框获得焦点: 使用 js 里面的 focus() 方法
var search = document.querySelector('input');
document.addEventListener('keyup', function(e) {
if (e.keyCode === 83) {
search.focus();
}
})
</script>
- 案例:模拟京东快递单号查询
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
jd_input.addEventListener('keyup', function () {
if (this.value == '') {
con.style.display = 'none';
} else {
con.style.display = 'block';
con.innerText = this.value;
}
})
// 失去焦点则隐藏
jd_input.addEventListener('blur', function () {
con.style.display = 'none';
})
// 获得焦点则显示
jd_input.addEventListener('focus', function () {
if (this.value !== '') {
con.style.display = 'block';
}
})
</script>