一、DOM事件流
事件流 描述的是从页面中接收事件的顺序
事件 发生时会在元素节点之间按照特定的顺序传播,这个 传播过程 即 DOM事件流
DOM事件流分为3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
- 事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程(
从下往上) - 事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程(
从上往下)
注意:
- JS代码中只能执行捕获或者冒泡其中的 一个阶段
- onclick 和 attachEvent 只能得到冒泡阶段
- addEventListener(type,listener[,useCapture]) 第三个参数如果是 true,表示在事件 捕获阶段 调用事件处理程序;如果是 false (不写默认就是 false),表示在事件 冒泡阶段 调用事件处理程序
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseleave
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
dom 事件流 三个阶段
// 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
// 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
// 3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段 document -> html -> body -> father -> son
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, true);// 捕获
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, true); // father -> son
// 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段 son -> father ->body -> html -> document
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false);// 冒泡
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');// son->father->document
})
</script>
二、事件对象e
2.1、什么是事件对象?
官方解释:event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法
比如:
- 谁绑定了这个事件
- 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
- 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键
<div>123</div>
<script>
// 事件对象
var div = document.querySelector('div');
// 传统方法
div.onclick = function(event) {
console.log(event); //点击后才有
}
// 事件监听方法
div.addEventListener('click', function(e) {
console.log(e);
})
// 兼容性方法
div.onclick = function(e) {
e = e || window.event;
console.log(e);
}
</script>
- event 就是一个事件对象,写到我们侦听函数的小括号里面当形参来看
- 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
- 当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数) ,通过事件来记录文件读取进度或异常行为
- 事件对象是我们事件的一系列相关数据的集合,跟事件相关的比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标等;如果是键盘事件里面就包含的键盘事件的信息,比如判断用户按下了哪个键等
- 这个事件对象我们可以自己命名,比如 event、evt、e
- 事件对象也有兼容性问题 IE678 通过 window.event 兼容性的写法 e = e || window.event
2.2事件对象的常见属性和方法
| 事件对象属性方法 | 说明 |
|---|---|
| e.target | 返回触发事件的对象 标准 |
| e.srcElement | 返回触发事件的对象 非标准 IE6-8使用 |
| e.type | 返回事件的类型 比如 click、mouseover,不带 on |
| e.cancelBubble | 该属性阻止冒泡 非标准 IE6-8使用 |
| e.returnValue | 该属性阻止默认事件(默认行为) 非标准 IE6-8使用 比如不让链接跳转 |
| e.preventDefault() | 该方法阻止默认事件(默认行为) 标准 比如不让链接跳转 |
| e.stopPropagation() | 该方法阻止冒泡 标准 |
2.2.1 e.target 和 this 的区别
区别:e.target 点击了哪个元素,就返回哪个元素;this 哪个元素绑定了这个点击事件,那么就返回谁
// 常见事件对象的属性和方法
// 1 e.target 返回的是触发事件的对象(元素);this 返回的是绑定事件的对象(元素)
var div = document.querySelector('div');
div.addEventListener('click', function(e) {
console.log(e.target); //<div>123</div>
console.log(this); //<div>123</div>
})
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// e.target 指向我们点击的那个对象 谁触发了这个事件 我们点击的是 li e.target指向的就是li
console.log(e.target); //点击的那一个 li
// 我们给ul绑定了事件 那么 this 就指向 ul
console.log(this); //ul 包括里面的li
console.log(e.currentTarget); //跟 this 有个非常相似的属性 e.currentTarget (了解) 缺点:兼容性问题 IE678不认识
})
// 兼容性处理(了解)
div.onclick = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
}
2.2.2返回事件类型
// 返回事件类型
var div = document.querySelector('div');
div.addEventListener('clcik', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type);
}
2.2.3阻止默认行为
// 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); //dom 标准写法
})
// 传统的注册方式
a.onclick = function(e) {
// 普通浏览器支持 e.preventDefault(); 方法
e.preventDefault();
// 低版本浏览器 IE678 可以使用 returnValue 属性
e.returnValue;
// 可以利用 return false 也能阻止默认行为 没有兼容性问题 特点:return后面的代码不执行了,而且只限于传统的注册方式
return false;
}
2.2.4阻止事件冒泡的两种方式(重要)
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点
// son -> father ->body -> html -> document
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
e.stopPropagation(); //stop 停止 propagation 传播
//e.cancelBubble = true;//cancel 取消 bubble 泡泡 冒泡 IE678支持
}, false);// 冒泡
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
e.stopPropagation();
}, false);
document.addEventListener('click', function() {
alert('document'); // son->father->document
})
//阻止事件冒泡的兼容性解决方案
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}