DOM事件机制

一、事件流

​ ​ ​ ​ ​ ​ ​ 事件流描述了页面接收事件的顺序。DOM完整的事件流包括三个阶段:事件捕获阶段、目标阶段和事件冒泡阶段。

1、事件冒泡(IE事件流)

​ ​ ​ ​ ​ ​ ​ IE事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点) 开始触发,在冒泡阶段,事件冒泡,或者事件发生在它的父代,祖父母,直到到达window为止。

<div id="outer">outer
    <div id="center">center
      <div id="inner">inner</div>
    </div>
  </div>
var inner = document.getElementById('inner');
    var center = document.getElementById('center');
    var outer = document.getElementById('outer');
    // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样
    inner.onclick = function () {
      console.log('我是inner点击的');
    }
    // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象
    center.onclick = function () {
      console.log('我是center点击的');
    }
    outer.onclick = function () {
      console.log('我是outer点击的');
    }

在点击页面中的id为inner的div元素,click事件会以如下顺序发生

  1. div#inner
  2. div#center
  3. div#outer
  4. body
  5. html
  6. document

在这里插入图片描述

2、事件捕获

​ ​ ​ ​ ​ ​ ​ 事件捕获就是由外往内,从事件发生的顶点开始,逐级往下查找,一直到目标元素。
​ ​ ​ ​ ​ ​ ​ 如果前面的例子使用事件捕获,则点击div元素会以下列顺序触发 click 事件:

  1. document
  2. html
  3. body
  4. div

​ ​ ​ ​ ​ ​ ​ 在事件捕获中,click 事件首先由 document 元素捕获,然后沿 DOM 树依次向下传播,直至到达实际的目标元素div。
在这里插入图片描述

3、DOM事件流

​ ​ ​ ​ ​ ​ ​ 事件通过捕获到达目标元素,这个时候就是目标阶段。从目标节点元素将事件上传到根节点的过程就是第三个阶段,冒泡阶段。
在这里插入图片描述
​ ​ ​ ​ ​ ​ ​ 在 DOM 事件流中,实际的目标(div元素)在捕获阶段不会接收到事件。这是因为捕获阶段从document 到html再到body就结束了。下一阶段,即会在div元素上触发事件的“到达目标”阶段,通常在事件处理时被认为是冒泡阶段的一部分。然后,冒泡阶段开始,事件反向传播至文档。

二、事件处理程序

​ ​ ​ ​ ​ ​ ​ 事件意味着用户或浏览器执行的某种动作。比如,单击(click)、加载(load)、鼠标悬停(mouseover)。为响应事件而调用的函数被称为事件处理程序(或事件监听器)。事件处理程序的名字以"on"开头,因此 click 事件的处理程序叫作 onclick,而 load 事件的处理程序叫作 onload。有很多方式可以指定事件处理程序。

1、DOM0 事件处理程序

DOM0 级事件分两种,一是直接在标签内直接添加执行语句,二是定义执行函数。

<input type="text" id="test">
<input type="button" value="button" onclick="alert(document.getElementById('test').value)">

<script>
        document.getElementById('button').onclick=function(){
            alert(document.getElementById('test').value);
        }
</script> 

2、DOM2 级事件处理程序

DOM2 Events 为事件处理程序的赋值和移除定义了两个方法:

addEventListener()remove EventListener()。

这两个方法暴露在所有 DOM 节点上,它们接收 3 个参数:

第一个参数:事件名称
第二个参数:执行函数
第三个参数:指定冒泡还是捕获,默认是false,冒泡。

element.addEventListener('click',function(){},false)

三、事件对象

​ ​ ​ ​ ​ ​ ​ 在 DOM 中发生事件时,所有相关信息都会被收集并存储在一个名为 event 的对象中。这个对象包含了一些基本信息,比如导致事件的元素、发生的事件类型,以及可能与特定事件相关的任何其他数据。例如,鼠标操作导致的事件会生成鼠标位置信息,而键盘操作导致的事件会生成与被按下的键有关的信息。所有浏览器都支持这个 event 对象,尽管支持方式不同。

1、阻止默认事件发生

preventDefault()方法

​ ​ ​ ​ ​ ​ ​ 用于阻止特定事件的默认动作。比如,链接的默认行为就是在被单击时导航到 href 属性指定的 URL或是修改表单提交的默认事件。如果想阻止这些行为,可以在 onclick 事件处理程序中取消,如下面的例子所示:

<a href="http://www.baidu.com">跳转</a>
<form action="./1-HTML事件处理程序.html">
  <button id="btn">提交按钮</button>
</form>
<script>
  var a = document.getElementsByTagName('a')[0];
  var btn = document.getElementById('btn');
  a.onclick = function (event) {
    // alert(1);
    // 阻止事件默认行为
    event.preventDefault();
  }
  btn.onclick = function (event) {
    // 阻止事件默认行为
    event.preventDefault();
  }
</script>

四、事件委托

​ ​ ​ ​ ​ ​ ​ 事件委托,又名事件代理。事件委托就是利用事件冒泡,就是把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托也就没法实现了。
例如,click 事件冒泡到 document。这意味着可以为整个页面指定一个 onclick 事件处理程序,而不用为每个可点击元素分别指定事件处理程序。比如有以下HTML:

<ul id="myLinks">
  <li id="li1">Go somewhere</li>
  <li id="li2">Do something</li>
  <li id="li3">Say hi</li>
</ul>

​ ​ ​ ​ ​ ​ ​ 这里的 HTML 包含 3 个列表项,在被点击时应该执行某个操作。对此,通常的做法是像这样指定 3个事件处理

<script>
  var item1 = document.getElementById("li1");
  var item2 = document.getElementById("li2");
  var item3 = document.getElementById("li3");
  item1.addEventListener('click', function () {
    this.innerHTML = 'SuZhou';
  })
  item2.addEventListener('click', function () {
    this.innerHTML = 'Coding';
  })
  item3.addEventListener('click', function () {
    this.innerHTML = 'Hi';
  })
</script>

​ ​ ​ ​ ​ ​ ​ 如果对页面中所有需要使用 onclick 事件处理程序的元素都如法炮制,结果就会出现大片雷同的只为指定事件处理程序的代码。使用事件委托,只要给所有元素共同的祖先节点添加一个事件处理程序,就可以解决问题。

比如:

<script>
  var list = document.getElementById("myLinks");
  list.addEventListener("click", function (event) {
    var target = event.target;
    console.log(target);
    switch (target.id) {
      case "li1":
        target.innerHTML = 'SuZhou';
        break;
      case "li2":
        target.innerHTML = 'Coding';
        break;
      case "li3":
        target.innerHTML = 'Hi';
        break;
    }
  });
</script>

​ ​ ​ ​ ​ ​ ​ 这里只给<ul id="myLinks">元素添加了一个 onclick 事件处理程序。因为所有列表项都是这个元素的后代,所以它们的事件会向上冒泡,最终都会由这个函数来处理。但事件目标是每个被点击的列表项,只要检查 event 对象的 id 属性就可以确定,然后再执行相应的操作即可。相对于前面不使用事件委托的代码,这里的代码不会导致先期延迟,因为只访问了一个 DOM 元素和添加了一个事件处理程序。结果对用户来说没有区别,但这种方式占用内存更少。所有使用按钮的事件(大多数鼠标事件和键盘事件)都适用于这个解决方案。

五、事件类型

​ ​ ​ ​ ​ ​ ​ Web 浏览器中可以发生很多种事件。如前所述,所发生事件的类型决定了事件对象中会保存什么信息。DOM3 Events 定义了如下事件类型。

1、用户界面事件(UIEvent)

:涉及与 BOM 交互的通用浏览器事件。

  • load

    在 window 上当页面加载完成后触发,在窗套(< frameset >)上当所有窗格(< frame >)

    都加载完成后触发,在元素上当图片加载完成后触发,在元素上当相应对象加

    载完成后触发。

<script>
  window.onload = function () {
    console.log('onload');
  }
</script>
  • unload

    当页面完全卸载后在window上触发,当所有框架都卸载后在框架集上触发,当嵌入的内容卸载完毕后再上触发。

  • select

    在文本框(或 textarea)上当用户选择了一个或多个字符时触发。

<input type="text" id="inp">
<script>
  var inp = document.getElementById('inp');
  inp.onselect = function (event) {
    console.log(event);
    // 可以通过window.getSelection()获取到选中的部分
    console.log(window.getSelection().toString());
  }
</script>
  • resize

    在 window 或窗格上当窗口或窗格被缩放时触发。

<body onresize="myFun()">
  <script>
    function myFun() {
      console.log(window.outerHeight, window.outerWidth);
    }
  </script>
</body>
  • scroll

    当用户滚动包含滚动条的元素时在元素上触发。元素包含已加载页面的滚动条。

    大多数 HTML 事件与 window 对象和表单控件有关。

<div id="d1" style="width: 100px;height: 100px;border: 1px solid; overflow: auto;">我是div标签我是div标签我是div标签我是div标签我是div标签我是div标签我是div标签我是div标签我是div标签我是div标签我是div标签</div>
<script>
  var d1 = document.getElementById('d1');
  d1.onscroll = function () {
    console.log('onscroll');
  }
</script>

2、焦点事件(FocusEvent)

:在元素获得和失去焦点时触发。

  • blur

    当元素失去焦点时触发。这个事件不冒泡,所有浏览器都支持。

  • focus

    当元素获得焦点时触发。这个事件不冒泡,所有浏览器都支持。

<input type="text" id="inp1">
<script>
  var inp1 = document.getElementById('inp1');
  // 失去焦点触发
  inp1.onblur = function () {
    console.log('失去焦点');
    console.log(this.value);
  }
  // 获得焦点触发
  inp1.onfocus = function () {
    console.log('获得焦点');
  }
</script>
  • focusin

    当元素获得焦点时触发。这个事件是 focus 的冒泡版。

  • focusout

    当元素失去焦点时触发。这个事件是 blur 的冒泡版。

3、鼠标事件(MouseEvent)和 滚轮事件(WheelEvent)

:使用鼠标在页面上执行某些操作时触发。使用鼠标滚轮(或类似设备)时触发。

  • click

    在用户单击鼠标主键(通常是左键)或按键盘回车键时触发。这主要是基于无障碍的考虑,让键盘和鼠标都可以触发 onclick 事件处理程序。

  • dblclick

    在用户双击鼠标主键(通常是左键)时触发。这个事件不是在 DOM2 Events 中定义的,但得到了很好的支持,DOM3 Events 将其进行了标准化。

  • mousedown

    在用户按下任意鼠标键时触发。这个事件不能通过键盘触发。

  • mouseenter

    在用户把鼠标光标从元素外部移到元素内部时触发。这个事件不冒泡,也不会在光标经过后代元素时触发。mouseenter 事件不是在 DOM2 Events 中定义的,而是 DOM3 Events中新增的事件。

  • mouseleave

    在用户把鼠标光标从元素内部移到元素外部时触发。这个事件不冒泡,也不会在光标经过后代元素时触发。mouseleave 事件不是在 DOM2 Events 中定义的,而是 DOM3 Events中新增的事件。

  • mousemove

    在鼠标光标在元素上移动时反复触发。这个事件不能通过键盘触发。

  • mouseout

    在用户把鼠标光标从一个元素移到另一个元素上时触发。移到的元素可以是原始元素的外部元素,也可以是原始元素的子元素。这个事件不能通过键盘触发。

  • mouseover

    在用户把鼠标光标从元素外部移到元素内部时触发。这个事件不能通过键盘触发。

  • mouseup

    在用户释放鼠标键时触发。这个事件不能通过键盘触发。

  • mousewheel

    鼠标滚轮事件

4、键盘事件(KeyboardEvent)和 输入事件(InputEvent)

:使用键盘在页面上执行某些操作时触发。

  • keydown

用户按下键盘上某个键时触发,而且持续按住会重复触发。

  • keypress

用户按下键盘上某个键并产生字符时触发,而且持续按住会重复触发。Esc 键也会触发这个事件。DOM3 Events 废弃了 keypress 事件,而推荐 textInput 事件。

  • keyup

用户释放键盘上某个键时触发。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值