从事件到事件传播

104 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
打牢基础慢慢走

结论

事件传播分为三个阶段:

  1. 捕获阶段
  2. 目标阶段
  3. 冒泡阶段 好了这就结束了,这就是事件传播机制最简单的答案。
    简单的了解了一下事件的传播机制,那么什么是事件呢?

什么是事件?

事件是您在编程时系统内发生的动作或者发生的事情,系统响应事件后,如果需要,您可以某种方式对事件做出回应

上方就是MDN的解释。通过这些可以简单的知道事件就是系统内发生的动作或事情,那么我们平时经常说绑定事件,如果不进行绑定,事件还会存在吗?答案是肯定的,而我们经常说的事件绑定,只是对事件的回应。

事件是系统内本来就规定或者定义好的,无论我们是否进行所谓的事件绑定,它都是存在的。

截屏2022-05-25 22.23.19.png
通过打印body我们看到是一个对象,那么我们展开这个对象就会看到很多类似下方图片展示的属性(只截取了一部分,因为这部分有我们都熟悉的onclick) 截屏2022-05-25 22.25.15.png
图2

了解了什么是事件,我们继续向下进行

事件都有哪些种类呢?

在MDN上能找到很多的事件的类型,感兴趣的可以看一下。今天看到了一个比较有意思的事件reset。
为什么说它有意思呢,是看到它突然想到很多时候我们提交表单后需要将表单置空表单,但是有多少人表单置空的方法是将每个input的value值重新复制为空呢? 其实大可不用那么麻烦,下方的代码就简单的解决了

<form id="form">
    <input type="text">
    <input type="text">
    ...
</form>
<button id="bt">提交</button>
<script>
bt.onclick = function (e) {
  document.getElementById("form").reset()
}
</script>

事件绑定

click才是事件,但是上方截图中说的却是onclick属性。这是因为它是一种事件绑定的方式。

  1. 绑定事件的方式有两种:

    1. DOM 0级
      形式:el.on[事件名称] = function(){}
      依据:它依据的是每一个图2中,每一个DOM元素都会存在on[事件名称]这样的私有属性

    2. DOM 2级 形式:el.addEventListener([事件名称],fn,bol) 依据:它依据的是原型链
      tips:控制台打印console.dir(document.body),按照body->HTMLBodyElement->HTMLElement->Element->Node->EventTarget:addEventListener的路径,就能够发现(IE9以下不支持,但现在是不是可以不考虑这些浏览器了)。

  2. 两种绑定方式的区别

    • 使用方式不同(这不是废话嘛)
    • 依据不同
    • DOM 0级事件的触发在事件传播的2、3阶段,不可更改。但DOM 2级可以通过最后的bol参数进行更改,如果为false(默认值)在2、3阶段触发,为true在1、2阶段触发
    • 相同事件绑定方法个数不同:DOM 0级相同事件只能绑定一个方法,如果绑定多个,后边绑定的会替换掉前边的事件,DOM 2级可以绑定多个方法,并且全部执行

事件传播

文章最开始已经给出了结论,下边看一下图片吧

R-C.png
白话一下,事件的传播就像是古时候发生了重大的杀人案件,那么怎么解决呢?
普天之下莫非皇土,这是时候皇上发话指定A省破案,A省调查后发现犯人是B市的,A省指定给B市破案,B市调查后发现犯人是C县的,B市指定给C县破案【捕获阶段】。C县经过努力破除了案件【目标阶段】,C县押解犯人给B市审批,B市发现没有问题,B市押解犯人A省审批,A省发现没问题押解犯人给皇上【冒泡阶段】。

在冒泡阶段,也就是破除案件到最后押解犯人给皇上这过程中,有一个环节不想继续上报了怎么办呢?

阻止冒泡:使用ev.stopPropagation?ev.stopPropagation():ev.cancelBubble = true

那么如何阻止事件的默认行为呢?e.preventDefault?e.preventDefault():e.returnValue=true或者在事件绑定的方法中return false,但是这种方法不适合用在a标签上。

留一个小问题:

为什么大多情况下使用mouseenter和mouseleave而不是使用mouseover和mouseout呢?