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);

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):