JavaScript:事件源与事件流
事件源
在事件中,当前操作的那个元素就是事件源。比如网页元素中 input 有 onclick 事件,当点击 input 发送 onclic 事件时,事件源就是 input。
常见事件源:
(鼠标) 事件 | 描述 |
---|---|
onclick | 鼠标单击对象时触发 |
ondblclick | 鼠标双击对象时触发 |
onmousedown | 鼠标按钮被按下时触发 |
onmousemove | 鼠标被移动时触发 |
onmouseout | 鼠标离开监听该事件的元素或子元素时触发 |
onmouseover | 鼠标移动到监听该事件的元素或子元素时触发 |
onmouseup | 鼠标松开时触发 |
(键盘) 事件 | 描述 |
---|---|
onkeydown | 键盘按下 |
keypress | 键盘按住 |
keyup | 键盘松开 |
(表单控件) 事件 | 描述 |
---|---|
onblur | 失去焦点 |
onfocus | 获取焦点 |
oninput | 输入 |
onchange | 改变 |
onsubmit | 提交 |
onreset | 重置 |
(页面) 事件 | 描述 |
---|---|
onload | 页面加载结束 |
onscroll | 滚动 |
onresize | 改变大小 |
获取事件源:
事件源是作为event对象的属性存在的。在W3C规范中,这个属性是 target ;但是 IE8.0 及其以下版本不支持该属性,它使用 srcElement 属性来获取事件源。
<html>
<head>
<title>获取事件源</title>
</head>
<body>
<div id="demo">点击这里</div>
<script type="text/javascript">
document.getElementById("demo").onclick=function(e){
var eve = e || window.event;
var srcNode = eve.target || eve.srcElement; // 兼容所有浏览器
alert(srcNode);
}
</script>
</body>
</html>
事件流:
描述的是从页面中接收事件的顺序,也可以理解为事件的传播顺序。
DOM事件流存在的三个阶段:
- 事件捕获阶段
- 处于目标阶段
- 事件冒泡阶段
事件捕获(event capturing):当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。
事件冒泡(dubbed bubbling):与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。
DOM标准事件流的触发的先后顺序为:先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。
不同的浏览器对此有着不同的实现,IE10及以下不支持捕获型事件,所以就少了一个事件捕获阶段,IE11、Chrome 、Firefox、Safari等浏览器则同时存在。
target 和 currentTarget
- target是触发事件的某个具体的对象,只会出现在事件机制的目标阶段,即"谁触发了事件,谁就是target"。
- currentTarget是绑定了当前事件类型的对象,有可能是目标节点的祖先节点。
阻止事件在冒泡阶段传播
event.stopPropagation
//阻止事件在冒泡阶段传播
<!-- 例子结构 -->
<div id="outer">
<p id="inner"></p>
</div>
/**
* 点击#inner之后会发生如下过程:
* outer捕获阶段
* inner 一
* inner 二
* inner 三
*/
const inner = document.querySelector('#inner');
const outer = document.querySelector('#outer');
inner.addEventListener("click", event => {
console.log("inner 一");
}, false);
inner.addEventListener("click", event => {
console.log("inner 二");
event.stopPropagation();
}, false);
inner.addEventListener("click",event => {
console.log("inner 三");
}, false);
outer.addEventListener("click", event => {
console.log("outer捕获阶段");
}, false);
outer.addEventListener("click", event => {
console.log("outer冒泡阶段");
}, false);
如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了event.stopImmediatePropagation()
方法,则当前元素剩下的监听函数将不会被执行,并且阻止事件在冒泡阶段传播。
/**
* 点击#inner之后会发生如下过程:
* outer捕获阶段
* inner 一
* inner 二
*/
const inner = document.querySelector('#inner');
const outer = document.querySelector('#outer');
inner.addEventListener("click", (event) => {
console.log("inner 一");
}, false);
inner.addEventListener("click", (event) => {
console.log("inner 二");
event.stopImmediatePropagation();
}, false);
inner.addEventListener("click",(event) => {
console.log("inner 三");
}, false);
outer.addEventListener("click", event => {
console.log("outer捕获阶段");
}, false);
outer.addEventListener("click", event => {
console.log("outer冒泡阶段");
}, false);
发表评论 (审核通过后显示评论):