JavaScript系列——事件
事件的定义
在W3的定义
中,事件具有三个状态,分别对应三个状态码,1,2,3.有多个可读的属性,常用的比如目标(target),当前目标(currentTarget),还有阻止继续事件传播(captrue/bubble)方法,stopPropagation。
// PhaseType
const unsigned short CAPTURING_PHASE = 1;
const unsigned short AT_TARGET = 2;
const unsigned short BUBBLING_PHASE = 3;
readonly attribute DOMString type;
readonly attribute EventTarget target;
readonly attribute EventTarget currentTarget;
readonly attribute unsigned short eventPhase;
readonly attribute boolean bubbles;
readonly attribute boolean cancelable;
readonly attribute DOMTimeStamp timeStamp;
void stopPropagation();
void preventDefault();
void initEvent(in DOMString eventTypeArg,
in boolean canBubbleArg,
in boolean cancelableArg);
};
事件的传播
在 JavaScript 中,时间传播分为三个阶段:
- 捕获阶段
- 目标触发阶段
- 冒泡阶段
捕获阶段:事件从 window 对象传导到目标节点上(target)。
具体有 W3 的 定义
Capture operates from the top of the tree, generally the Document, downward, making it the symmetrical opposite of bubbling which is described below. www.w3.org
在 addEventListener 函数中,可以设置 useCaptrue 为 true,在window 自下而上传导的过程中就捕捉:
ele.addEventListener("event", handle, true);
目标触发:事件到达目标之后执行,例如 onclick 等函数。
冒泡阶段:事件从目标节点回传到 window 对象。
我们用下面的代码做一下实验:
<html>
<head>
<meta charset="utf-8">
<title>Exep</title>
</head>
<body>
<div>
<p>click me</p>
</div>
<script>
var container = document.querySelector('div');
var para = document.querySelector('p');
var phase = {
1: "capture",
2: "target",
3: "bubble"
};
container.addEventListener('click',handle,true);
para.addEventListener('click',handle,true);
container.addEventListener('click',handle,false);
para.addEventListener('click',handle,false);
function handle(event) {
var tag = event.currentTarget.tagName;
var phaseName = phase[event.eventPhase];
console.log("tag: " + tag + ".phase: " + phaseName);
}
</script>
</body>
</html>
/* log
"tag: DIV.phase: capture"
"tag: P.phase: target"
"tag: P.phase: target"
"tag: DIV.phase: bubble"
*/
EventTarget
eventTarget 有三个方法 分别是 addEventListener 和removeEventListener,dispatchEvent();
target.addEventListener(type, listener[, useCaptrue]);该方法用于在某节点或对象中监听特定事件(listener)。useCpatrue 可以设置为 true,是在捕获阶段监听,false为冒泡阶段监听,默认为false。
如果使用 ele.on-handle 监听事件,则只会在冒泡阶段触发。on-函数是元素的一个属性值,可以在setAttribute 中赋值。
EventTarget.addEventListener 和 on-handle 的区别:
- addEventListener 可以同一个设置多个监听函数。
- 能够事件哪个阶段(捕获/冒泡)触发监听函数。
- 所有的文档对象都可以使用 addEventListener 接口。
on-handle 的缺点:
- 违反了 HTML 和 JavaScript 分离的代码规范,不易于模块化和拓展性。
- 一个事件只能定义一个监听函数,后定义者后来居上。
事件的代理
由于事件的传播机制,可以将子节点的事件绑定到父节点,然后利用event.target 定位到该元素
// html
<div class="flipBox">
<div class="login"></div>
</div>
// javasript
$('.flipBox').addEventListener('click', function(e){
e.stopPropagation();
if(e.target.classList.contains('login')) {
$('.flipBox').classList.remove('register');
$('.flipBox').classList.add('login');
}
this 的指向
听函数内部的this指向触发事件的那个元素节点。
// HTML
// <button id="btn">点击</button>
var btn = document.getElementById('btn');
// 写法一
btn.onclick = function () {
console.log(this.id);
};
// 写法二
btn.addEventListener(
'click',
function (e) {
console.log(this.id);
},
false
);
// 输出 "btn"
参考阅读