事件Events

  • 事件是javascript的核心,你看到的任何javascript脚本都是由事件触发。网页的交互性,在JS中事件是必不可少的。
  • 事件可以是用户的行为,也一些事件不是用户触发,比如:页面的加载

    事件发展历史

  1. 简单事件处理浏览器刚发明出来,跳转链接就是最简单的鼠标触发事件。
  2. 事件流处理随着其他事件种类的产生,问题随之而来。对于嵌套元素,父子元素同时绑定相同的事件,当事件触发时,这两个嵌套元素事件流的执行顺序该如何确定?
  3. 伴随着浏览器大战,微软和网景公司给出了不一样的答案。
    1. 微软公司采用事件冒泡模型,即先执行子元素,再执行父元素。
    2. 网景公司采用事件捕获模型,即先执行父元素,再执行子元素。
  4. 随后W3C制定标准事件模型
    1. 采用了两家公司的折中的办法,两种模型都支持。

      事件三要素

      image.png
  • 事件源
  • 事件对象
  • 事件监听器

    事件流

    为什么会有事件流?

    我的想法对于元素的嵌套,且每个元素都绑定了相同的事件。当你点击一个元素,你没法判断到底是怎么样的执行顺序,这会发生冲突问题。到底是父元素优先级高,还是子元素的优先级高。我想应该遍避免在全局document上绑定事件,同时要阻止事件冒泡。
    易错点有一些简单事件并没有事件流。比如:fouse、blur、change、submit、reset、select

    事件冒泡

    image.png

  • 最开始是目标元素触发click事件,然后在DOM上逐层向上传递,直到window对象。

    1. //事件冒泡会一直到window对象
    2. <body>
    3. <div class="box1">
    4. <span>盒子1</span>
    5. <div class="box2">
    6. <span>盒子2</span>
    7. </div>
    8. </div>
    9. </body>
    10. <script>
    11. let box1 = document.getElementsByClassName('box1')[0];
    12. let box2 = document.getElementsByClassName('box2')[0];
    13. box1.onclick = () => {console.log('我是盒子1')};
    14. box2.onclick = () => {console.log('我是盒子2')};
    15. document.onclick = () => {console.log('我是盒子document')};
    16. window.onclick = () => {console.log('我是盒子window')};
    17. </script>

    事件捕获

    image.png

  • 最开始是在window对象触发click事件,然后在DOM上逐层向下传递,直到目标节点对象。

  • 这种模型提供了拦截事件的可能,但是目标事件也没办法触发。也只有这种特殊情况才会使用它。
  • 总结下来,没法阻止事件捕获,一旦阻止事件捕获,目标事件又不会触发。

    DOM事件流

    image.png

  • 兼容上面两个事件模型。通过事件对象中的addEventListener方法,设定参数会执行不同的事件流模型。


我的想法事件流决定了事件监听节点,事件响应的先后顺序,也就是节点队列。
举例在DOM事件流模型中,不同的节点规定不同的事件流,节点队列的排序就是事件捕获的节点 -> 目标节点 -> 事件冒泡的节点。当浏览器接收到事件消息,事件处理引擎依照节点队列依次响应事件。

<body>
  <div class="box1">
    <span>盒子1</span>
    <div class="box2">
      <span>盒子2</span>
    </div>
  </div>
</body>
<script>
  let box1 = document.getElementsByClassName('box1')[0];         
  let box2 = document.getElementsByClassName('box2')[0];

  window.addEventListener('click', () => console.log('我是盒子window'), true);
  document.addEventListener('click', () => console.log('我是盒子document'), true);
  box1.addEventListener('click', () => console.log('我是盒子1'), false); 
  box2.addEventListener('click', () => console.log('我是盒子2'), false); 

</script>