【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 -> … -> 某个具体的元素

 冒泡型事件流:

<style>
      * {
        color: white;
        font-size: 20px;
      }
      #outer {
        width: 300px;
        height: 300px;
        background-color: lightpink;
      }
      #center {
        width: 200px;
        height: 200px;
        background-color: lightgreen;
      }
      #inner {
        width: 100px;
        height: 100px;
        background-color: lightskyblue;
      }
    </style>
  </head>
  <body>
    <div id="outer">
      outer
      <div id="center">
        center
        <div id="inner">inner</div>
      </div>
    </div>
    <script>
      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点击的");
      };
    </script>
  </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(&quot;Clicked&quot;)">点我啊</button>

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

<!-- 需要加() -->
<button onclick="showMsg()">点我啊</button>
<script>
  function showMsg() {
    console.log('Hello Wolrd!');
  }
</script>


在这个函数中,this 值相当于事件的目标元素,如下面的例子所示:

<button onclick="this.innerHTML = '我被改变了'">点我啊</button>

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

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

<button id="btn">点我</button>
    <script>
        // DOM0
        var btn = document.getElementById('btn')
        btn.onclick = function(event){
            console.log('我被打中了');    
            console.log(this.id); //btn

        }
     </script>

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

移除事件程序:

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

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

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

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

addEventListener()和removeEventListener()

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

         <button id="btn">点我</button>
     <script>

        var btn = document.getElementById('btn')

        // 单纯添加事件处理程序
        btn.addEventListener('click',function(){
            console.log('怎么又被打中了');
        },false)
        btn.addEventListener('click',function(){
            console.log(this.id);  // btn
        })
    </script>

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

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

<button id='btn'>点我啊</button>
<script>
  var btn = document.getElementById("btn");
  btn.addEventListener("click", function () {
    console.log('我被点击了');
  }, false);
  // 移除
  btn.removeEventListener("click", function () {
    console.log(this.id); //没有效果
  })
</script>

解绑事件要具名: 

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

<button id='btn'>点我啊</button>
<script>
  var btn = document.getElementById("btn");
  // 新增一个方法
  var handler = function () {
    console.log(this.id);
  }
  btn.addEventListener("click", handler, false);
  // 移除
  btn.removeEventListener("click", handler, false); // 有效果
</script>

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

事件对象

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

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

阻止默认事件发生

preventDefault()方法

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

<form action="./1-class01.html">
        <button id="btn">提交</button>
    </form>
    <script>
        // 组织a事件的默认事件发生
        var a = document.getElementsByTagName('a')[0]
        a.onclick = function(event){
            event.preventDefault();
            console.log('a被点中了');
        }
        var f = document.getElementById('btn')
        btn.onclick = function(event){
            event.preventDefault();
            console.log('┗|`O′|┛ 嗷~~');
        }
    </script>

事件委托和事件代理


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

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

如·:

 

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340