DOM事件机制

发布于:2023-01-04 ⋅ 阅读:(682) ⋅ 点赞:(0)

目录

前言 

一、事件的组成

二、执行事件的步骤

三、事件流

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

1.1 阻止事件冒泡

2、事件捕获 (Netscape事件流)

3、DOM事件流

四、事件处理程序

1、HTML 事件处理程序

2、DOM0事件处理程序

移除事件处理程序

3、DOM2 事件处理程序

addEventListener()

removeEventListener()

五、事件对象 event

阻止默认事件发生

preventDefault() 方法

event.target和event.currentTarget区别 

六、事件委托

七、事件类型

1、用户界面事件

load

unload

select

resize

scroll

2、焦点事件

blur

focus

focusin

focusout

3、鼠标事件和鼠标滚轮事件

click

dblclick

mousedown

mouseenter

mouseleave

mousemove

mouseout

mouseover

mouseup

mousewheel

4、键盘事件与输入事件

keydown

keypress

keyup

textInput


前言 

HTML DOM 允许 JavaScript 对 HTML 事件作出反应。JavaScript 能够在事件发生时执行,比如当用户点击某个 HTML 元素时。

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

一、事件的组成

事件由三部分组成:事件源、事件类型、事件处理程序

事件源:事件被触发的对象,例如按钮对象

事件类型:如何触发?触发什么事件?例如鼠标点击,键盘按下等…

事件处理程序:通过一个函数赋值的方式

二、执行事件的步骤

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 采用函数赋值形式添加事件处理程序

三、事件流

在第四代 Web 浏览器(IE4 和 Netscape Communicator 4)开始开发时,开发团队碰到了一个有意思的问题:页面哪个部分拥有特定的事件呢?要理解这个问题,可以在一张纸上画几个同心圆。把手指放到圆心上,则手指不仅是在一个圆圈里,而且是在所有的圆圈里。两家浏览器的开发团队都是以同样的方式看待浏览器事件的。当你点击一个按钮时,实际上不光点击了这个按钮,还点击了它的容器以及整个页面。

事件流描述了页面接收事件的顺序。结果非常有意思,IE 和 Netscape 开发团队提出了几乎完全相反的事件流方案。IE 将支持事件冒泡流,而 Netscape Communicator 将支持事件捕获流。

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

IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。

来看一个例子:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      text-align: center;
      font-size: 20px;
    }

    #outer {
      width: 300px;
      height: 300px;
      border-radius: 50%;
      background-color: pink;
    }

    #center {
      width: 200px;
      height: 200px;
      border-radius: 50%;
      background-color: rgb(69, 194, 236);
      margin: 25px auto;
    }

    #inner {
      width: 100px;
      height: 100px;
      border-radius: 50%;
      background-color: rgb(49, 214, 96);
      margin: 25px auto;
    }
  </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.onclick = function () {
      console.log('我是inner点击的');
    }
    center.onclick = function () {
      console.log('我是center点击的');
    }
    outer.onclick = function () {
      console.log('我是outer点击的');
    }
  </script>
</body>

</html>

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

  1. div#inner

  2. div#center

  3. div#outer

  4. body

  5. html

  6. document

也就是说,div#inner元素,即被点击的元素,最先触发 click 事件。然后,click 事件沿DOM 树一路向上,在经过的每个节点上依次触发,直至到达 document 对象。

所有现代浏览器都支持事件冒泡,只是在实现方式上会有一些变化。IE5.5及早期版本会跳过html元素(从body直接到 document)。现代浏览器中的事件会一直冒泡到 window 对象。

1.1 阻止事件冒泡

我们使用 event.stopPropagation() 可阻止事件冒泡。

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。这是DOM事件默认提供的一个对象,HTML DOM Event对象。事件通常与函数结合使用,函数不会在事件发生前被执行!

给上面例子中的事件添加event.stopPropagation()来阻止冒泡:

inner.onclick = function () {
  event.stopPropagation()
  console.log('我是inner点击的');
}
center.onclick = function () {
  event.stopPropagation()
  console.log('我是center点击的');
}
outer.onclick = function () {
  console.log('我是outer点击的');
}

2、事件捕获 (Netscape事件流)

Netscape Communicator 团队提出了另一种名为事件捕获的事件流。事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。如果前面的例子使用事件捕获,则点击div元素会以下列顺序触发 click 事件:

  1. document

  2. html

  3. body

  4. div

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

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

3、DOM事件流

DOM2 Events 规范规定事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。

点击div元素会以如图所示的顺序触发事件:

在 DOM 事件流中,实际的目标(div元素)在捕获阶段不会接收到事件。这是因为捕获阶段从document 到html再到body就结束了。下一阶段,即会在div元素上触发事件的“到达目标”阶段,通常在事件处理时被认为是冒泡阶段的一部分。然后,冒泡阶段开始,事件反向传播至文档。大多数支持 DOM 事件流的浏览器实现了一个小小的拓展。虽然 DOM2 Events 规范明确捕获阶段不命中事件目标,但现代浏览器都会在捕获阶段在事件目标上触发事件。最终结果是在事件目标上有两个机会来处理事件。

注意:所有现代浏览器都支持 DOM 事件流,只有 IE8 及更早版本不支持。

四、事件处理程序

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

1、HTML 事件处理程序

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

<button onclick="console.log('按钮被点击了')">点击我</button>

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

<body>
  <!-- 注意要添加() -->
  <button onclick="handler()">点击我</button>
  <script>
    function handler(){
      console.log('按钮被点击了');
    }
  </script>
</body>

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

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

2、DOM0事件处理程序

在 JavaScript 中指定事件处理程序的传统方式是把一个函数赋值给(DOM 元素的)一个事件处理程序属性。这也是在第四代 Web 浏览器中开始支持的事件处理程序赋值方法,直到现在所有现代浏览器仍然都支持此方法,主要原因是简单。要使用 JavaScript 指定事件处理程序,必须先取得要操作对象的引用。每个元素(包括 window 和 document)都有通常小写的事件处理程序属性,比如 onclick。只要把这个属性赋值为一个函数即可:

<body>
  <button id="btn">点击我</button>
  <script>
    var btn = document.getElementById('btn')
    btn.onclick = function(){
      console.log('按钮被点击了');
      //这里的this指向 html元素button本身
      console.log(this); //<button id="btn">点击我</button>
      console.log(this.id); //btn
      console.log(this.className); //btn1
    } 
  </script>
</body>

像这样使用 DOM0 方式为事件处理程序赋值时,所赋函数被视为元素的方法。因此,事件处理程序会在元素的作用域中运行,即 this 等于元素本身。 在事件处理程序里通过 this 可以访问元素的任何属性和方法。以这种方式添加事件处理程序是注册在事件流的冒泡阶段的。

移除事件处理程序

把事件处理程序设置为 null 就可以移除事件处理程序:

btn.onclick = null

如果事件处理程序是在 HTML 中指定的,则 onclick 属性的值是一个包装相应HTML 事件处理程序属性值的函数。这些事件处理程序也可以通过在 JavaScript 中将相应属性设置为 null 来移除:

<body>
  <button onclick="console.log('按钮被点击了')">点击我</button>
  <script>
    var btn = document.getElementsByTagName('button')[0]
    //设置onclick属性的值为null即可移除事件处理程序
    btn.setAttribute('onclick', 'null')
  </script>
</body>

3、DOM2 事件处理程序

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

addEventListener() 和 removeEventListener()

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

addEventListener()

与 DOM0 方式类似,这个事件处理程序同样在被附加到的元素的作用域中运行。使用 DOM2方式的主要优势是可以为同一个事件添加多个事件处理程序。多个事件处理程序以添加顺序来触发:

<body>
  <button>点击我</button>
  <script>
    var btn = document.getElementsByTagName('button')[0]
    btn.addEventListener('click', function(){
      console.log('按钮被点击了');
    })
    btn.addEventListener('click', function(){
      console.log(this);
    })
  </script>
</body>

removeEventListener()

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

<body>
  <button>点击我</button>
  <script>
    var btn = document.getElementsByTagName('button')[0]
    btn.addEventListener('click', function(){
      console.log('按钮被点击了');
    })
    //移除
    btn.removeEventListener('click', function(){
      console.log('按钮被点击了');
    }) //无效,无法移除
  </script>
</body>

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

<body>
  <button>点击我</button>
  <script>
    var btn = document.getElementsByTagName('button')[0]
    function handler(){
      console.log('按钮被点击了');
    }
    btn.addEventListener('click', handler)
    //移除
    btn.removeEventListener('click', handler) //移除成功
  </script>
</body>

 大多数情况下,事件处理程序会被添加到事件流的冒泡阶段,主要原因是跨浏览器兼容性好。把事件处理程序注册到捕获阶段通常用于在事件到达其指定目标之前拦截事件。如果不需要拦截,则不要使用事件捕获。

五、事件对象 event

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

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

阻止默认事件发生

preventDefault() 方法

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

<body>
  <a href="https://www.baidu.com">百度一下,你就知道</a>
  <!-- 表单提交 -->
  <form action="test.php">
    <input type="submit" value="提交" id="inp1">
  </form>
  <script>
    // 阻止a标签的默认事件发生
    var a = document.getElementsByTagName('a')[0]
    a.onclick = function () {
      event.preventDefault();
      console.log('a被点击了');
    }
    // 阻止表单事件的默认行为
    var inp1 = document.getElementById('inp1')
    inp1.onclick = function () {
      event.preventDefault();
      console.log('表单提交了');
    }
  </script>
</body>

event.target和event.currentTarget区别 

target是触发事件的源头,currentTarget是正在执行的事件。
前者是事件触发源元素,目标事件
后者是当前正在执行事件的元素,当前目标事件

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		#outer{
			width: 300px;
			height: 300px;
			background-color: red;
		}
		#center{
			width: 200px;
			height: 200px;
			background-color: blue;
		}
		#inner{
			width: 100px;
			height: 100px;
			background-color: yellow;
		}
	</style>
	<script>
		window.onload=function(){
			var outer=document.getElementById('outer');
			var center=document.getElementById('center');
			var inner=document.getElementById('inner');
			outer.onclick=function(event){
				console.log('我是outer');
				console.log(event.target,'触发目标事件的源');
				console.log(event.currentTarget,'当前正在执行事件的元素');
			}
			center.onclick=function(event){
				console.log('我是center');
				console.log(event.target,'触发目标事件的源');
				console.log(event.currentTarget,'当前正在执行事件的元素');
			}
			inner.onclick=function(event){
				console.log('我是inner');
				console.log(event.target,'触发目标事件的源');
				console.log(event.currentTarget,'当前正在执行事件的元素');
			}
		}
	</script>
</head>
<body>
	<div id="outer">
		<div id="center">
			<div id="inner"></div>
		</div>
	</div>
</body>
</html>

当点击黄色的div时,得到如下结果:

六、事件委托

在 JavaScript 中,页面中事件处理程序的数量与页面整体性能直接相关。原因有很多。首先,每个函数都是对象,都占用内存空间,对象越多,性能越差。其次,为指定事件处理程序所需访问 DOM 的次数会先期造成整个页面交互的延迟。只要在使用事件处理程序时多注意一些方法,就可以改善页面性能。

事件委托就是当事件触发时,把要做的事委托给父元素(或父元素的父元素)来处理。也就是:利用冒泡的原理,把事件加到父级上,通过判断事件来源的子集,执行相应的操作。使用事件委托技术能让你避免对特定的每个节点添加事件监听器。

事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,click 事件冒泡到 document。这意味着可以为整个页面指定一个 onclick 事件处理程序,而不用为每个可点击元素分别指定事件处理程序。

不使用事件委托:

<body>
  <ul id="father">
    <li id="li1">去哪</li>
    <li id="li2">吃啥</li>
    <li id="li3">干啥</li>
  </ul>
  <script>
    // 分别获取三个子元素的节点
    var li1 = document.getElementById('li1')
    var li2 = document.getElementById('li2')
    var li3 = document.getElementById('li3')
    // 分别给三个子元素节点绑定事件
    li1.onclick = function () {
      console.log('苏州');
    }
    li2.onclick = function () {
      console.log('螺蛳粉,吃不着');
    }
    li3.onclick = function () {
      console.log('敲代码');
    }
  </script>
</body>

使用事件委托:

<body>
  <ul id="father">
    <li id="li1">去哪</li>
    <li id="li2">吃啥</li>
    <li id="li3">干啥</li>
  </ul>
  <script>
    // 获取父元素节点
    var father = document.getElementById('father')
    father.addEventListener('click', function (event) {
      // console.log(event.target.id);
      switch (event.target.id) {
        case 'li1':
          console.log('苏州');
          break;
        case 'li2':
          console.log('螺蛳粉,吃不着');
          break;
        case 'li3':
          console.log('敲代码');
          break;
        default:
          break;
      }
    })
  </script>
</body>

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

扩展:

只要可行,就应该考虑只给 document 添加一个事件处理程序,通过它处理页面中所有某种类型的事件。相对于之前的技术,事件委托具有如下优点:

  1. document 对象随时可用,任何时候都可以给它添加事件处理程序(不用等待 DOMContentLoaded或 load 事件)。这意味着只要页面渲染出可点击的元素,就可以无延迟地起作用。
  2. 节省花在设置页面事件处理程序上的时间。只指定一个事件处理程序既可以节省 DOM 引用,也可以节省时间。
  3. 减少整个页面所需的内存,提升整体性能。

最适合使用事件委托的事件包括:click、mousedown、mouseup、keydown 和 keypress。

七、事件类型

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

用户界面事件(UIEvent):涉及与 BOM 交互的通用浏览器事件。

焦点事件(FocusEvent):在元素获得和失去焦点时触发。

鼠标事件(MouseEvent):使用鼠标在页面上执行某些操作时触发。

滚轮事件(WheelEvent):使用鼠标滚轮(或类似设备)时触发。

键盘事件(KeyboardEvent):使用键盘在页面上执行某些操作时触发。

输入事件(InputEvent):向文档中输入文本时触发。

1、用户界面事件

load

在 window 上当页面加载完成后触发,在窗套(<frameset>)上当所有窗格(<frame>)都加载完成后触发,在<img>元素上当图片加载完成后触发,在<object>元素上当相应对象加载完成后触发。

<body>
  <img src="https://img2.baidu.com/it/u=3090637020,2183334079&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1661446800&t=c2c2f83d94349aa432d29782f6c9a471" alt="">
  <script>
    // onload 监听某些事情是否加载完毕
    //window上当页面加载完成后执行 console.log('window.onload');
    window.onload = function () {
      console.log('window.onload');
    }
    //等待图片加载完后执行 console.log('img onload');
    document.getElementsByTagName('img')[0].onload = function () {
      console.log('img onload');
    }
  </script>
</body>

unload

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

select

在文本框(<input>或 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.outerWidth, window.outerHeight);
    }
  </script>
</body>

scroll

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

大多数 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、焦点事件

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 的冒泡版。

<body>
  <div style="width: 300px; height: 200px; border: 1px solid red;" id="d1">
    <input id="inp" type="text">
  </div>
  <script>
    var d1 = document.getElementById('d1');
    var inp = document.getElementById('inp');
    
    // 失去焦点触发
    d1.addEventListener('focusout',handler1)
    // 获得焦点触发
    d1.addEventListener('focusin',handler)
    
    function handler() {
      d1.style.backgroundColor = 'blue'
      console.log('获得焦点触发');
    }
    function handler1() {
      d1.style.backgroundColor = 'pink'
      console.log('失去焦点触发');
    }
  </script>
</body>

3、鼠标事件和鼠标滚轮事件

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

鼠标滚轮事件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #d1{
      width: 300px;
      height: 300px;
      background-color: aqua;
    }
  </style>
</head>
<body>
  <div id="d1"></div>
  <script>
    var d1 = document.getElementById('d1');
    // 单击事件
    d1.onclick = function (event) {
      console.log('click');
      console.log(event);
    }
    // 双击事件
    d1.ondblclick = function () {
      console.log('dblclick');
    }
    // 鼠标移入事件
    d1.onmouseenter = function () {
      console.log('mouseenter');
    }
    // 鼠标移出事件
    d1.onmouseleave = function () {
      console.log('mouseleave');
    }
    // 鼠标在元素内部移动时触发
    d1.onmousemove = function () {
      console.log('mousemove');
    }
  </script>
</body>
</html>

4、键盘事件与输入事件

键盘事件是用户操作键盘时触发的。DOM2 Events 最初定义了键盘事件,但该规范在最终发布前删除了相应内容。因此,键盘事件很大程度上是基于原始的 DOM0 实现的。

DOM3 Events 为键盘事件提供了一个首先在 IE9 中完全实现的规范。其他浏览器也开始实现该规范,但仍然存在很多遗留的实现。

键盘事件包含 3 个事件:

keydown

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

keypress

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

keyup

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

虽然所有元素都支持这些事件,但当用户在文本框中输入内容时最容易看到。

输入事件只有一个,即:

textInput

这个事件是对 keypress 事件的扩展,用于在文本显示给用户之前更方便地截获文本输入。textInput 会在文本被插入到文本框之前触发。当用户按下键盘上的某个字符键时,首先会触发 keydown 事件,然后触发 keypress 事件,最后触发 keyup 事件。注意,这里 keydown 和 keypress 事件会在文本框出现变化之前触发,而 keyup事件会在文本框出现变化之后触发。如果一个字符键被按住不放,keydown 和 keypress 就会重复触发,直到这个键被释放。对于非字符键,在键盘上按一下这个键,会先触发 keydown 事件,然后触发 keyup 事件。如果按住某个非字符键不放,则会重复触发 keydown 事件,直到这个键被释放,此时会触发 keyup 事件。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="text" id="inp1">
  <script>
    var inp1 = document.getElementById('inp1');
    // 按下某个按键时触发
    inp1.onkeydown = function (event) {
      if (event.keyCode == 13) {
        console.log('确认');
        console.log(this.value);
      }
    }
    // 按下键盘上某个键并产生字符时触发,而且持续按住会重复触发
    inp1.onkeypress = function (event) {
      console.log(event.keyCode);
    }
    // 用户释放键盘上某个键时触发
    inp1.onkeyup = function (event) {
      console.log(event.keyCode);
    }
    // 键盘输入事件 必须使用DOM2级事件
    inp1.addEventListener('textInput', function (event) {
      console.log(event.data);
    })
  </script>
</body>
</html>

本文含有隐藏内容,请 开通VIP 后查看