文章目录
DOM事件机制
1、简介
HTML DOM 允许 JavaScript 对 HTML 事件作出反应。JavaScript 能够在事件发生时执行,比如当用户点击某个 HTML 元素时。JavaScript与HTML之间的交互是通过事件实现的。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。
<div id='div1'>我是一个div</div>
<button id='btn1'>点我啊1</button>
<!-- 同样可以直接在HTML标签中进行事件的绑定-->
<button id='btn2' onclick="clickFun()">点我啊2</button>
<script>
// 点击按钮,改变div的内容,大小,背景颜色
// 分别获取div和button的节点
var div = document.getElementById('div1');
var btn = document.getElementById('btn1');
// 如需向 HTML 元素分配事件,能够使用事件属性。给按钮节点绑定点击事件
btn.onclick = function () {
div.innerHTML = '点击按钮1改变的';
div.style.width = '200px';
div.style.height = '200px';
div.style.backgroundColor = 'red';
}
// 执行在btn2中绑定的事件
function clickFun() {
div.innerHTML = '点击按钮2改变的';
div.style.width = '200px';
div.style.height = '200px';
div.style.backgroundColor = 'green';
}
</script>
- 事件由三部分组成
事件源、事件类型、事件处理程序 我们也称为事件三要素
1.事件源:事件被触发的对象 ,例如,按钮对象
2.事件类型:如何触发?触发什么事件?例如鼠标点击动作,鼠标点击后的抬起动作,键盘按下等…
3.事件处理程序:通过一个函数赋值的方式
- 执行事件的步骤
1.获取事件源
2.注册事件(绑定事件)
3.采用函数赋值形式添加事件处理程序
- 常用事件
当用户鼠标点击时
当网页加载后
当图像加载后
当鼠标移至元素上时
当输入字段被改变时
当 HTML 表单被提交时
当用户敲击按键时
…
2、事件流
2.1 简介
事件流描述了页面接收事件的顺序。
2.2 分类
2.2.1 事件冒泡流(IE事件流)
IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。
事件冒泡,就是元素自身的事件被触发后,如果父元素有相同的事件,如onclick事件,那么元素本身的触发状态就会传递,也就是冒到父元素,父元素的相同事件也会一级一级根据嵌套关系向外触发,直到document/window,冒泡过程结束。
例如:
<!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>
<div id="outer">outer
<div id="center">center
<div id="inner">inner</div>
</div>
</div>
</body>
</html>
<style>
*{
color: white;
font-size: 20px;
}
#outer{
width: 300px;
height: 300px;
background-color: red;
}
#center{
width: 200px;
height: 200px;
background-color: blue;
}
#inner{
width: 100px;
height: 100px;
background-color: green;
}
</style>
<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>
点击inner时,
在点击inner后再点击center时,
在点击inner、center后再点击outer
分析:在点击页面中的id为inner的div元素,click事件会以如下顺序发生
由内向外
- div#inner
- div#center
- div#outer
- body
- html
- document
也就是说,div#inner元素,即被点击的元素,最先触发 click 事件。然后,click 事件沿DOM 树一路向上,在经过的每个节点上依次触发,直至到达 document 对象。
所有现代浏览器都支持事件冒泡,只是在实现方式上会有一些变化,现代浏览器中的事件会一直冒泡到 window 对象。
阻止事件冒泡
事件冒泡在某些应用场景产生一些问题,就是我们不需要触发的事件,由于冒泡的原因,也会运行。所以在这个时候要阻止事件冒泡。
使用阻止事件冒泡之前,先要知道DOM事件默认提供的一个对象,HTML DOM Event对象。Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。事件通常与函数结合使用,函数不会在事件发生前被执行。
通过event.stopPropagation()
方法阻止事件冒泡。
例如:
<!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>
<div id="outer">outer
<div id="center">center
<div id="inner">inner</div>
</div>
</div>
</body>
</html>
<style>
*{
color: white;
font-size: 20px;
}
#outer{
width: 300px;
height: 300px;
background-color: red;
}
#center{
width: 200px;
height: 200px;
background-color: blue;
}
#inner{
width: 100px;
height: 100px;
background-color: green;
}
</style>
<script>
var inner = document.getElementById('inner');
var center = document.getElementById('center');
var outer = document.getElementById('outer');
// 当只有一个inner点击方法的时候 发现想要实现的效果和预期的一样
inner.onclick = function (event) {
console.log('我是inner点击的');
//event 事件对象
console.log(event,"这是阻止事件之前的");
//阻止事件对象
event.stopPropagation();
console.log(event,"这是阻止事件之后的")
}
// 但是当给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象
center.onclick = function () {
console.log('我是center点击的');
}
outer.onclick = function () {
console.log('我是outer点击的');
}
</script>
在点击inner后,center、outer绑定的事件没有再接着执行了,这就达到了阻止冒泡事件的作用。
2.2.2 事件捕获流(NetScape事件流)
Netscape Communicator 团队提出了另一种名为事件捕获的事件流。事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。如果前面的例子使用事件捕获,则点击div元素会以下列顺序触发 click 事件:
- document
- html
- body
- div
在事件捕获中,click 事件首先由 document 元素捕获,然后沿 DOM 树依次向下传播,直至到达实际的目标元素div。
2.2.3 DOM事件流
DOM2 Events 规范规定事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。
还是上面那个例子,点击div元素会以如图所示的顺序触发事件:
在 DOM 事件流中,实际的目标(div元素)在捕获阶段不会接收到事件。这是因为捕获阶段从document 到html再到body就结束了。下一阶段,即会在div元素上触发事件的“到达目标”阶段,通常在事件处理时被认为是冒泡阶段的一部分。然后,冒泡阶段开始,事件反向传播至文档。大多数支持 DOM 事件流的浏览器实现了一个小小的拓展。虽然 DOM2 Events 规范明确捕获阶段不命中事件目标,但现代浏览器都会在捕获阶段在事件目标上触发事件。最终结果是在事件目标上有两个机会来处理事件。
通常使用的事件流都是冒泡事件流,特殊情况使用事件捕获流,DOM事件流所有浏览器都支持(处IE8及其更早版本)。
3、事件处理程序
3.1 简介
事件意味着用户或浏览器执行的某种动作。比如,单击(click)、加载(load)、鼠标悬停(mouseover)。为响应事件而调用的函数被称为事件处理程序(或事件监听器)。事件处理程序的名字以"on"开头,因此 click 事件的处理程序叫作 onclick,而 load 事件的处理程序叫作 onload。有很多方式可以指定事件处理程序。
3.2 HTML事件处理程序
特定元素支持的每个事件都可以使用事件处理程序的名字以 HTML 属性的形式来指定。此时属性的值必须是能够执行的 JavaScript 代码。例如,要在按钮被点击时执行某些 JavaScript 代码,可以使用以下 HTML 属性:
<button onclick="console.log('Clicked')">点我</button>
点击这个按钮后,控制台会输出一条消息。这种交互能力是通过为 onclick 属性指定 JavaScript代码值来实现的。
注意,因为属性的值是 JavaScript 代码,所以不能在未经转义的情况下使用 HTML 语法字符,比如和号(&)、双引号(")、小于号(<)和大于号(>)。此时,为了避免使用 HTML 实体,可以使用单引号代替双引号。如果确实需要使用双引号,则要把代码改成下面这样:<button onclick="console.log("Clicked")">点我</button> /*"代表双引号*/
在 HTML 中定义的事件处理程序可以包含精确的动作指令,也可以调用在页面其他地方定义的方法。例如:
<!-- 注意需要再函数名后需要加() -->
<button onclick="showMsg()">点我啊</button>
<script>
function showMsg() {
console.log('Hello Wolrd!');
}
</script>
或者
<div id="click">点我</div>
<script>
var click = document.getElementById("click");
click.onclick = function(event){
console.log("我是被点击了");
}
</script>
此外,this的使用如下:
<button onclick="this.innerHTML = '我被改变了'">点我啊</button>
这里的this 值相当于事件的目标元素
3.3 DOM0事件处理程序
在 JavaScript 中指定事件处理程序的传统方式是把一个函数赋值给(DOM 元素的)一个事件处理程序属性。这也是在第四代 Web 浏览器中开始支持的事件处理程序赋值方法,直到现在所有现代浏览器仍然都支持此方法,主要原因是简单。要使用 JavaScript 指定事件处理程序,必须先取得要操作对象的引用。每个元素(包括 window 和 document)都有通常小写的事件处理程序属性,比如 onclick。只要把这个属性赋值为一个函数即可:
<button id='btn'>点我</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
console.log('我被点击了');
}
</script>
这里先从文档中取得按钮,然后给它的 onclick 事件处理程序赋值一个函数。
需要注意的是,前面的代码在运行之后才会给事件处理程序赋值。因此如果在页面中上面的代码出现在按钮之后,则有可能出现用户点击按钮没有反应的情况。像这样使用 DOM0 方式为事件处理程序赋值时,所赋函数被视为元素的方法。因此,事件处理程序会在元素的作用域中运行,即 this 等于元素,例如下面的例子就是this引用元素本身。
<button id='btn'>点我</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
console.log('我被点击了');
console.log(this.id); //btn
}
</script>
点击按钮,这段代码会显示元素的 ID。这个 ID 是通过 this.id 获取的。
不仅仅是 id,在事件处理程序里通过 this 可以访问元素的任何属性和方法。
以这种方式添加事件处理程序是注册在事件流的冒泡阶段的。
- 移除DOM0事件处理程序
通过将事件处理程序属性的值设置为 null,可以移除通过 DOM0 方式添加的事件处理程序,如下面的例子所示
btn.onclick = null;
把事件处理程序设置为 null,再点击按钮就不会执行任何操作了。
如果事件处理程序是在 HTML 中指定的,则 onclick 属性的值是一个包装相应HTML 事件处理程序属性值的函数。这些事件处理程序也可以通过在 JavaScript 中将相应属性设置为 null 来移除。
<button id="button0" onclick="console.log('我被点击了')">点我</button>
<script>
var btn = document.getElementById("button0");
btn.onclick = null; //清除事件处理程序
</script>
3.4 DOM2事件处理程序
DOM2 Events为事件处理程序的赋值和移除定义了两个方法:addEventListener()和removeEventListener()。
这两个方法暴露在所有 DOM 节点上,它们接收 3 个参数:事件名、事件处理函数和一个布尔值,true 表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事件处理程序。
addEventListener()方法
以给按钮添加 click 事件处理程序为例,可以这样写:
<button id='btn'>点我</button>
<script>
var btn = document.getElementById("btn");
btn.addEventListener("click", function () {
console.log('我被点击了');
}, false);
//第三个参数false为冒泡,从内向外,true为捕获,从外向内
</script>
以上代码为按钮添加了会在事件冒泡阶段触发的 onclick 事件处理程序(因为最后一个参数值为false)。与 DOM0 方式类似,这个事件处理程序同样在被附加到的元素的作用域中运行。使用 DOM2方式的主要优势是可以为同一个事件添加多个事件处理程序。来看下面的例子:
<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。
removeEventListener()方法
通过 addEventListener()添加的事件处理程序只能使用 removeEventListener()并传入与添加时同样的参数来移除。
<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); // 有效果
btn.removeEventListener("click",function () {
console.log('我被点击了');
}, false); //无效果
</script>
大多数情况下,事件处理程序会被添加到事件流的冒泡阶段,主要原因是跨浏览器兼容性好。把事件处理程序注册到捕获阶段通常用于在事件到达其指定目标之前拦截事件。如果不需要拦截,则不要使用事件捕获。
4、事件对象event
在 DOM 中发生事件时,所有相关信息都会被收集并存储在一个名为 event 的对象中。这个对象包含了一些基本信息,比如导致事件的元素、发生的事件类型,以及可能与特定事件相关的任何其他数据。例如,鼠标操作导致的事件会生成鼠标位置信息,而键盘操作导致的事件会生成与被按下的键有关的信息。所有浏览器都支持这个 event 对象,尽管支持方式不同。并且event 对象只在事件处理程序执行期间存在,一旦执行完毕,就会被销毁。
preventDefault()方法
用于阻止特定事件的默认动作。比如,链接的默认行为就是在被单击时导航到 href 属性指定的 URL或是修改表单提交的默认事件。如果想阻止这些行为,可以在 onclick 事件处理程序中取消,如下面的例子所示:
/*a标签有默认跳转功能*/
<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) {
// 阻止事件默认行为
event.preventDefault();
}
btn.onclick = function (event) {
// 阻止事件默认行为
event.preventDefault();
}
</script>
注意:阻止事件默认行为与阻止事件冒泡是两个概念。
阻止事件默认行为:event.preventDefault;
阻止事件冒泡:
1.javascript的return false只会阻止默认行为,而使用jQuery的话则既阻止默认行为又防止对象冒泡。
$(‘.btn’).on(‘click’,function(event){
do something …
return false
})
2. W3C: event.stopPropagation();
IE: event.cancelBubble = true
5、事件委托*
在 JavaScript 中,页面中事件处理程序的数量与页面整体性能直接相关。原因有很多。首先,每个函数都是对象,都占用内存空间,对象越多,性能越差。其次,每次为指定事件添加事件处理程序会导致所需访问 DOM 的次数增多,会先期造成整个页面交互的延迟。只要在使用事件处理程序时多注意一些方法,就可以改善页面性能。
事件委托就是当事件触发时,把要做的事委托给父元素(或父元素的父元素)来处理。也就是:利用冒泡的原理,把事件加到父级上,通过判断事件来源的子集,执行相应的操作。使用事件委托技术能让你避免对特定的每个节点添加事件监听器。
事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,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) {
//表达式的值和值1/值2/值3匹配上时,需要执行的代码
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 元素和添加了一个事件处理程序。结果对用户来说没有区别,但这种方式占用内存更少。所有使用按钮的事件(大多数鼠标事件和键盘事件)都适用于这个解决方案。
只要可行,就应该考虑只给 document 添加一个事件处理程序,通过它处理页面中所有某种类型的事件。相对于之前的技术,事件委托具有如下优点。
- document 对象随时可用,任何时候都可以给它添加事件处理程序(不用等待 DOMContentLoaded或 load 事件)。这意味着只要页面渲染出可点击的元素,就可以无延迟地起作用。
- 节省花在设置页面事件处理程序上的时间。只指定一个事件处理程序既可以节省 DOM 引用,也可以节省时间。
- 减少整个页面所需的内存,提升整体性能。
最适合使用事件委托的事件包括:click、mousedown、mouseup、keydown 和 keypress。
6、事件类型
Web 浏览器中可以发生很多种事件。如前所述,所发生事件的类型决定了事件对象中会保存什么信息。有如下事件类型。
用户界面事件(UIEvent):涉及与 BOM 交互的通用浏览器事件。
焦点事件(FocusEvent):在元素获得和失去焦点时触发。
鼠标事件(MouseEvent):使用鼠标在页面上执行某些操作时触发。
滚轮事件(WheelEvent):使用鼠标滚轮(或类似设备)时触发。
键盘事件(KeyboardEvent):使用键盘在页面上执行某些操作时触发。
输入事件(InputEvent):向文档中输入文本时触发。
用户界面事件
- load
在 window 上当页面加载完成后触发,在窗套()上当所有窗格()都加载完成后触发,在元素上当图片加载完成后触发,在元素上当相应对象加载完成后触发。
<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>
焦点事件
-
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 的冒泡版。
鼠标事件和滚轮事件
鼠标事件是 Web 开发中最常用的一组事件,这是因为鼠标是用户的主要定位设备。DOM3 Events定义了 9 种鼠标事件。
-
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>
键盘事件和输入事件
-
键盘事件
键盘事件是用户操作键盘时触发的。DOM2 Events 最初定义了键盘事件,但该规范在最终发布前删除了相应内容。因此,键盘事件很大程度上是基于原始的 DOM0 实现的。
DOM3 Events 为键盘事件提供了一个首先在 IE9 中完全实现的规范。其他浏览器也开始实现该规范,但仍然存在很多遗留的实现。- keydown
用户按下键盘上某个键时触发,而且持续按住会重复触发。 - keypress
用户按下键盘上某个字符键时触发,而且持续按住会重复触发。DOM3 Events 废弃了 keypress 事件,而推荐 textInput 事件。 - keyup
用户释放键盘上某个键时触发。
- keydown
-
输入事件
输入事件只有一个,即 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>
虽然从字面理解, KeyDown和keypressess都是按下一个键的意思, 但实际上二者的根本区别是,:
(1)系统由KeyDown返回键盘的代码, 然后由TranslateMessage函数翻译成成字符;
(2)而KeyPress直接返回字符值.
因此在KeyDown中返回的是键盘的代码, 而KeyPress返回的是ASCII字符. 所以根据你的目的, 如果只想读取字符, 用KeyPress, 如果想读各键的状态, 用KeyDown.