• 【DOM】-- 事件机制


    目录

    DOM事件

    事件的组成:(事件三要素)

    执行步骤:

     常用事件:

     DOM事件流

    事件流的分类

     冒泡型事件流:

    阻止事件冒泡

     捕获型事件流

    DOM事件流的三个阶段

    事件处理程序

    HTML事件处理程序

    DOM0 事件处理程序

    DOM2 事件处理程序

    事件对象

    阻止默认事件发生

    preventDefault()方法

    事件委托和事件代理


    DOM事件

    HTML DOM允许JS对HTML事件作出反应,当对某个元素进行操作时执行JavaScript代码。

    JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。

    事件的组成:(事件三要素)

    1. 事件源:事件被触发的对象 --- 按钮对象
    2. 事件类型:如和触发?触发什么事件?--- 鼠标点击,键盘按下……
    3. 事件处理程序:通过函数赋值

    执行步骤:

    1. 获取事件源

    2. 绑定事件(注册事件)

    3. 采用函数赋值的方式添加事件处理程序 

     常用事件:

     DOM事件流

    简单来说,事件流就是事件执行的顺序。DOM树里会有许多元素嵌套,当我们同时给父子元素设置了事件时,父子元素会以一种特定的顺序来执行事件,这就是事件流。并且嵌套的层级不限,事件会贯穿当前元素与根元素。

    事件流的分类

    DOM支持两种事件流:冒泡型事件流 | 捕获型事件流

    • 冒泡型事件流:从特定的事件目标到外层的不特定的元素,由下往上,从叶子节点到根节点。 即:某个具体的元素-> … -> body -> html -> document -> window
    • 捕获型事件流:从最外层不特定的事件目标到特定的事件目标,由上往下,从DOM的根节点到叶子节点。即:: window -> document -> html -> body -> … -> 某个具体的元素

     冒泡型事件流:

    1. <style>
    2. * {
    3. color: white;
    4. font-size: 20px;
    5. }
    6. #outer {
    7. width: 300px;
    8. height: 300px;
    9. background-color: lightpink;
    10. }
    11. #center {
    12. width: 200px;
    13. height: 200px;
    14. background-color: lightgreen;
    15. }
    16. #inner {
    17. width: 100px;
    18. height: 100px;
    19. background-color: lightskyblue;
    20. }
    21. style>
    22. head>
    23. <body>
    24. <div id="outer">
    25. outer
    26. <div id="center">
    27. center
    28. <div id="inner">innerdiv>
    29. div>
    30. div>
    31. <script>
    32. var inner = document.getElementById("inner");
    33. var center = document.getElementById("center");
    34. var outer = document.getElementById("outer");
    35. // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样
    36. inner.onclick = function () {
    37. console.log("我是inner点击的");
    38. };
    39. // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象
    40. center.onclick = function () {
    41. console.log("我是center点击的");
    42. };
    43. outer.onclick = function () {
    44. console.log("我是outer点击的");
    45. };
    46. script>
    47. body>

    第一次只在 inner 上添加了事件,因此点击 inner 时只有 inner 上的事件被触发: 

     第二次我们在 center 和 outer 上也添加了点击事件,虽然我们只点击了 inner 但是 center 与 outer 上的事件也被触发了:

     事实上,这个click事件还会沿着DOM树一直到body,html,document。

    阻止事件冒泡

    在阻止冒泡之前,我们要知道一个对象叫 event ,它代表事件的状态,比如事件在其中发生的元素,键盘状态,鼠标位置,鼠标按钮状态等……

    事件通常与函数结合使用,函数不会在事件发生前被执行!

    直接在对应方法中使用 event.stopPropagation() 便可阻止事件冒泡。

    注意:如果点击方法时需要同时传递其他参数和event,直接传递event这个单词即可

     捕获型事件流

    在捕获型事件流中,click事件会首先被document捕获,然后沿着DOM树依次向下,直到事件的目标元素。

    由于旧版本浏览器不支持,因此实际当中几乎不会使用事件捕获。通常建议使用事件冒泡,特殊情况下可以使用事件捕获。

    DOM事件流的三个阶段

    事件捕获、到达目标、事件冒泡

    1. 捕获阶段:从window对象依次向下传播,到达目标节点,即为捕获阶段。捕获阶段不会响应任何事件
    2. 目标阶段:在目标节点触发事件,即为目标阶段
    3. 冒泡阶段:从目标阶段依次向上传播,到达window对象,即为冒泡阶段。

    事件处理程序

    为响应事件而调用的函数被称为事件处理程序(或事件监听器)。事件处理程序的名字以"on"开头,因此 click 事件的处理程序叫作 onclick,而 load 事件的处理程序叫作 onload。有很多方式可以指定事件处理程序。

    HTML事件处理程序

    特定元素支持的每个事件都可以使用事件处理程序的名字以 HTML 属性的形式来指定。此时的属性值必须是能够执行的 JavaScript 代码。例如,要在按钮被点击时执行某些 JavaScript 代码,可以使用以下 HTML 属性:

    <button onclick="console.log('Clicked')">点我啊button>

    点击这个按钮后,控制台会输出一条消息。

    注意,因为属性的值是 JavaScript 代码,所以不能在未经转义的情况下使用 HTML 语法字符,比如和号(&)、双引号(")、小于号(<)和大于号(>)。此时,为了避免使用 HTML 实体,可以使用单引号代替双引号。如果确实需要使用双引号,则要把代码改成下面这样:

    <button onclick="console.log("Clicked")">点我啊button>

    在 HTML 中定义的事件处理程序可以包含精确的动作指令,也可以调用在页面其他地方定义的方法。

    1. <button onclick="showMsg()">点我啊button>
    2. <script>
    3.  function showMsg() {
    4.    console.log('Hello Wolrd!');
    5. }
    6. script>
    7. 在这个函数中,this 值相当于事件的目标元素,如下面的例子所示:
    8. <button onclick="this.innerHTML = '我被改变了'">点我啊button>

    DOM 0级 事件处理程序 -- 事件不可以追加

    要使用 JavaScript 指定事件处理程序,必须先取得要操作对象的引用。每个元素(包括 window 和 document)都有通常小写的事件处理程序属性,比如 onclick。只要把这个属性赋值为一个函数即可:

    1. <script>
    2. // DOM0
    3. var btn = document.getElementById('btn')
    4. btn.onclick = function(event){
    5. console.log('我被打中了');
    6. console.log(this.id); //btn
    7. }
    8. script>

    点击按钮,这段代码会显示元素的 ID。这个 ID 是通过 this.id 获取的。不仅仅是 id,在事件处理程序里通过 this 可以访问元素的任何属性和方法。以这种方式添加事件处理程序是注册在事件流的冒泡阶段的。在DOM2 中也如此。 

    移除事件程序:

    btn.onclick = null; // 移除事件处理程序

    把事件处理程序设置为 null,再点击按钮就不会执行任何操作了。

    DOM 2级 事件处理程序  -- 事件可以追加

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

    addEventListener()和removeEventListener()

    这两个方法暴露在所有 DOM 节点上,它们接收 3 个参数:事件名、事件处理函数和一个布尔值,true 表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事件处理程序。

    1. <script>
    2. var btn = document.getElementById('btn')
    3. // 单纯添加事件处理程序
    4. btn.addEventListener('click',function(){
    5. console.log('怎么又被打中了');
    6. },false)
    7. btn.addEventListener('click',function(){
    8. console.log(this.id); // btn
    9. })
    10. script>

    这里给按钮添加了两个事件处理程序。多个事件处理程序以添加顺序来触发,因此前面的代码会先打印'我被点击了',然后显示元素ID。

    通过 addEventListener()添加的事件处理程序只能使用 removeEventListener()并传入与添加时同样的参数来移除。这意味着使用 addEventListener()添加的匿名函数无法移除,如:

    1. <script>
    2. var btn = document.getElementById("btn");
    3. btn.addEventListener("click", function () {
    4. console.log('我被点击了');
    5. }, false);
    6. // 移除
    7. btn.removeEventListener("click", function () {
    8. console.log(this.id); //没有效果
    9. })
    10. script>

    解绑事件要具名: 

     这个例子通过 addEventListener()添加了一个匿名函数作为事件处理程序。然后,又以看起来相同的参数调用了 removeEventListener()。但实际上,第二个参数与传给 addEventListener()的完全不是一回事。传给 removeEventListener()的事件处理函数必须与传给 addEventListener()的是同一个,如:

    1. <script>
    2. var btn = document.getElementById("btn");
    3. // 新增一个方法
    4. var handler = function () {
    5. console.log(this.id);
    6. }
    7. btn.addEventListener("click", handler, false);
    8. // 移除
    9. btn.removeEventListener("click", handler, false); // 有效果
    10. script>

    这个例子有效,因为调用 addEventListener()和 removeEventListener()时传入的是同一个函数。

    事件对象

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

    注意:event 对象只在事件处理程序执行期间存在,一旦执行完毕,就会被销毁。

    阻止默认事件发生

    preventDefault()方法

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

    1. "./1-class01.html">
    2. <button id="btn">提交button>
    3. <script>
    4. // 组织a事件的默认事件发生
    5. var a = document.getElementsByTagName('a')[0]
    6. a.onclick = function(event){
    7. event.preventDefault();
    8. console.log('a被点中了');
    9. }
    10. var f = document.getElementById('btn')
    11. btn.onclick = function(event){
    12. event.preventDefault();
    13. console.log('┗|`O′|┛ 嗷~~');
    14. }
    15. script>

    事件委托和事件代理


    事件委托:也就是事件代理,也就是将原本绑定在子元素身上的事件 委托 给父元素。让父元素去监听事件。其原理是利用事件冒泡。这意味着可以为整个页面指定一个 onclick 事件处理程序,而不用为每个可点击元素分别指定事件处理程序。

    优点:大大减少DOM操作和浏览器的重排和重绘,节省内存占用。也可以实现当新增对象时无需再次对其绑定事件。

    如·:

     

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

     使用事件委托,只要给所有元素共同的祖先节点添加一个事件处理程序,就可以解决代码大段雷同的问题:

     这里只给

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

  • 相关阅读:
    初识JavaScript
    记一次排查线上MySQL死锁过程,不能只会curd,还要知道加锁原理
    Field的使用
    DEFORMABLE DETR: DEFORMABLE TRANSFORMERS FOR END-TO-END OBJECT DETECTION (论文解析)
    旋转接头安装使用注意事项
    ES性能优化最佳实践- 检索性能提升30倍!
    ADSP-21569/ADSP-21593的开发入门(上)
    深入浅出了解华为云API网关的Gzip功能
    uniapp项目实践总结(二十一)日常开发方法汇总
    计算机视觉:池化层的作用是什么?
  • 原文地址:https://blog.csdn.net/qq_48802092/article/details/126510609