一、事件监听
1. 给元素监听事件的三种方式
-
第一种方式: 事件作为HTML标签的属性:
<div onclick="JS代码……" ondblclick="JS代码……"></div>
-
第二种方式: 事件作为元素对象的方法:
元素对象.onclick = function() {}; 元素对象.ondblclick = function() {};
-
第三种方式:使用 addEventListenrer 方法:
元素对象.addEventListener('click',回调函数);
- 第三种事件监听方式可以给同一个元素,监听多次相同的事件
- IE8浏览器不支持addEventListenrer,可以使用
attachEvent('onclick',回调函数)
2. 解除事件的监听
-
第一种和第二种方式监听的事件:
给元素对象重新设置事件,设置为空,将原来的覆盖
元素对象.onclick = null;
-
第三种方式监听的事件:
元素对象.removeEventListener('click',回调函数名)
- addEventListenrer 方法监听的事件,如果需要接触监听,不能使用匿名的回调函数
- IE8以及以下,使用datachEvent()解除
二、事件流
从用户在元素上发生动作到回调函数执行,会经历三个阶段:
-
捕获阶段:从window、document、html元素一直层层向下,找到目标元素(具体发生了动作的动作)
-
目标阶段:标志着捕获阶段的结束以及冒泡阶段的开始
-
冒泡阶段:从目标元素开始向上冒泡,直到html元素、document、window
事件的回调函数在冒泡阶段执行(事件在冒泡阶段触发)
addEventListener()设置第三个参数为true,回调函数将在捕获阶段执行
三、事件的回调函数中 this 的指向
事件的回调函数中,this的值是监听事件的元素!
<button onclick="func(this)">按钮1</button>
<button id="btn02">按钮2</button>
<button id="btn03">按钮3</button>
<script>
function func(cb) {
cb();
}
func(function () {
console.log(this);//window调用
});
// 定义函数
function func(ele) {
for (var i = 0; i < 10; i++) {
console.log('按钮1 被点击了');
}
console.log(ele); //ƒ () {console.log(this);//window调用}
console.log(this); //window
}
// 第二种方式 将事件作为元素对象的方法
var btn02 = document.querySelector('#btn02');
btn02.onclick = function () {
console.log('btn02 被点击了!', this); //<button id="btn02">按钮2</button>
};
// 第三种 使用元素对象的 addEventListner()
var btn03 = document.querySelector('#btn03');
btn03.addEventListener('click', function () {
console.log('btn03 被点击了!', this); //<button id="btn03">按钮3</button>
});
</script>
四、常用事件总结
1. 鼠标事件
事件 | 含义 |
---|---|
click | 单击 |
dblclick | 双击 |
contextmenu | 右击 |
mousedown | 鼠标按键按下 |
mouseup | 鼠标按键抬起 |
mousemove | 鼠标移动 |
mouseover | 鼠标移入 |
mouseout | 鼠标移出 |
mouseenter | 鼠标移入 |
mouseleave | 鼠标移出 |
2. 键盘事件
事件 | 含义 |
---|---|
keydown | 键盘按键按下 |
keyup | 键盘按键抬起 |
keypress | 键盘按键按下 |
keypress 和 keydown 的区别:
- 只有可输入字符对应的按键按下,可以press才能触发,所有的按键按下keydown都可以触发
- keypress会对输入的字符进行处理判断,可以区分大小写字母
哪些元素可以监听键盘事件?
- document对象
- 表单输入框、文本域
3. 文档事件
事件 | 含义 | |
---|---|---|
load | 文档加载完毕(页面中所有一切加载完毕) | |
DOMContentLoaded | 文档加载完毕(页面中所有的元素加载完毕)只能使用addEventListener | 监听 |
beforeunload | 文档关闭前触发(所在窗口关闭) |
文档事件需要监听到window或者body元素上
4. 表单事件
事件 | 含义 |
---|---|
submit | 监听给form元素,当表单提交的时候触发 |
reset | 监听给form元素,当表单重置的时候触发 |
focus() | 监听给表单控件,当获取到焦点时触发 |
blur() | 监听给表单控件,当失去焦点的时候触发 |
change | 监听给表单控件,当表单控件发生改变 |
select | 监听给输入框或文本域,里面的内容被选中时触发 |
input | 监听给输入框或文本域,里面的内容发生改变时触发 |
change事件:监听给输入框,触发change需要满足两个条件:输入框内容变换;输入框失去焦点
5. 图片事件
事件 | 含义 |
---|---|
load | 图片文件加载完毕 |
error | 图片加载失败 |
abort | 图片加载中断(了解) |
6. 其他事件
-
过渡事件
事件 含义 transitionstart 过渡开始,延迟结束 transitionrun 延迟开始的时候 transitionend 过渡结束 -
动画事件
事件 含义 animationstart 动画开始的时候,延迟结束 animationend 动画结束的时候,最后结束 animationiteration 动画执行多次,每次结束都触发 -
其他事件
事件 含义 scroll 滚动事件,可以监听给window或者内容会滚动的元素 resize 监听给window,视口大小发生改变,触发
五、Event 对象
1. 获取 Event 对象
事件的回调函数中可以接收到参数,该参数就是事件对象
// 第二种方式 将事件作为元素对象的方法
var btn02 = document.querySelector('#btn02');
btn02.onclick = function(ev) {
// var ev = ev || window.event; // 兼容性获取事件对象
console.log('btn02 被点击了!', ev);
};
// 第三种 使用元素对象的 addEventListner()
var btn03 = document.querySelector('#btn03');
btn03.addEventListener('click', function(event){
console.log('btn03 被点击了!', event);
});
2. 鼠标事件对象 MouseEvent 的属性和方法
事件 | 含义 |
---|---|
button | 鼠标按键的值0:左键;1:中间;2:右键 |
offsetX/offsetY | 鼠标在目标元素上的位置 |
clientX/clientY | 鼠标在视口上的位置 |
pageX/pageY | 鼠标在页面上的位置 |
screenX/screenY | 鼠标在屏幕上的位置 |
// 监听鼠标移动
box.onmousemove = function(event) {
// 获取鼠标的位置
p.innerHTML = '鼠标在目标元素上的位置:' + event.offsetX + ' , ' + event.offsetY + '<br>';
p.innerHTML += '鼠标在视口上的位置:' + event.clientX + ' , ' + event.clientY + '<br>';
p.innerHTML += '鼠标在页面上的位置:' + event.pageX + ' , ' + event.pageY + '<br>';
p.innerHTML += '鼠标在屏幕上的位置:' + event.screenX + ' , ' + event.screenY + '<br>';
// 计算鼠标在box上的位置 鼠标在视口上位置 - box元素在视口上的位置
var boxX = event.clientX - box.getBoundingClientRect().left;
var boxY = event.clientY - box.getBoundingClientRect().top;
p.innerHTML += '鼠标在box元素上的位置:' + boxX + ' , ' + boxY + '<br>';
};
3. 键盘事件对象 KeyborardEvent 的属性和方法
事件 | 含义 |
---|---|
which | 获取键盘按键对应的ASCII码 |
keyCode | 同which |
key | 获取键盘按键的值(字符串) |
document.onkeydown = function(event) {
console.log('which:',event.which);
console.log('keyCode:',event.keyCode);
console.log('key:',event.key);
}
4. 所有类型的事件对象都有的属性和方法
事件 | 含义 |
---|---|
type | 获取事件名称 |
timeStamp | 触发事件时的时间戳,从打开页面时间开始计算 |
target | 获取目标元素 |
document.onkeydown = function(event) {
console.log('type:', event.type);
}
document.onclick = function(event) {
console.log('type:', event.type);
console.log('timeStamp:', event.timeStamp);
console.log('目标元素:', event.target);
console.log('');
}
5. 阻止事件冒泡
调用事件对象.stopPropagation()
6. 浏览器的默认行为
-
浏览器有哪些默认行为
- 超链接点击可以跳转(click事件)
- 表单可以提交和重置(submit和reset事件)
- 点击提交按钮可以提交表单(click事件)
- 点击重置按钮可以重置表单(click事件)
- 右键菜单(任何元素都具有该默认行为)
-
阻止浏览器默认行为
-
事件对象.preventDefault()
调用该方法可以阻止 -
如果使用第二种事件监听方式,在回调函数
return false;
同样可以阻止
浏览器的默认行为在整个事件流程结束后(冒泡也结束了)才会发生
-
六、事件委托
事件委托的原理:
- 在祖先元素上监听事件,动作发生在后代元素上,会冒泡到祖先元素
- 利用
event.target
获取到目标元素,如果目标元素是符合条件的元素就执行相应的操作
事件委托能解决什么问题?
- 让新增的元素也具有事件
- 通过事件委托给大量元素监听事件
// 遍历删除按钮 添加单击事件
// deleteBtns.forEach(function(deleteBtn){
// deleteBtn.onclick = function() {
// tableBox.deleteRow(deleteBtn.parentElement.parentElement.rowIndex);
// };
// });
// 使用事件委托
tableBox.onclick = function(event) {
// 判断如果 目标元素是删除按钮再进行相关操作
if (event.target.classList.contains('delete-btn')) {
tableBox.deleteRow(event.target.parentElement.parentElement.rowIndex);
}
};
七、DOM 对象深入分析
1. 元素对象的原型链关系
div元素对象 -> HTMLDivElement.prototype -> HTMlElement.prototype -> Element.prototype -> Node.prototype -> EventTarget.prototype -> Object.prototype
2. 事件对象的原型链关系
鼠标事件对象 -> MouseEvent.prototype -> UIEvent.prototype -> Event.prototype -> Object.prototype
3. HTMLCollection 和 NodeList 的区别
-
HTMLCollection 对象
- 能够返回HTMLCollection 对象的属性和方法: getElementsByTagName()、getElementsByClassName()、children
- HTMLCollection 对象的成员只能是元素类型对象
- 没有 forEach 方法
- 是动态的集合,如果文档中新增了满足条件的元素,集合会自动更新
-
NodeList
- 能够返回 NodeList 对象的属性和方法: querySelectorAll()、getElementsByName()、childNodes
- NodeList 对象的成员可以是节点类型的对象(包括元素类型、document 等)
- 具有 forEach 方法
- 静态的集合
// 获取到所有li的集合,得到 HTMLCollection 对象
var liCollection = document.getElementsByTagName('li');
// 获取到所有li的集合,得到 NodeList 对象
var liNodes = document.querySelectorAll('li');
console.log(liCollection);
console.log(liNodes);
console.log('');
// 获取到ul元素
var ulBox = document.querySelector('#box');
// 创建一个li元素,并添加到 ul 中
var newLi = document.createElement('li');
newLi.innerHTML = '我是一个新的 LI';
ulBox.appendChild(newLi);
console.log(liCollection);
console.log(liNodes);