共计 18265 个字符,预计需要花费 46 分钟才能阅读完成。
事件
JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意义的时刻。
1. 事件流(把握)
事件流模仿了事件接管的程序 。IE 和 Netscape 开发团队提出了简直齐全相
反的事件流计划。IE 将反对事件冒泡流,而 Netscape Communicator 将反对事件捕捉流。
1.1 事件冒泡(了解、应用)
从最具体的元素(文档中最深的节点)开始触发,而后向上流传到没有那么具体的元素(文档)。
例如:
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
点击页面的 div
元素后,click
事件会以如下程序产生:
1). <div>
2). <body>
3). <html>
4). document
如图:
IE5.5 及晚期版本会跳过 <html>
元素(从 <body> 间接到 document)。古代浏览器中的事件会始终冒泡到 window 对象。
1.2 事件捕获(理解)
** 事件捕捉的意思是最不具体的节
点应该最先收到事件,而最具体的节点应该最初收到事件。事件捕捉实际上是为了在事件达到最终目标
前拦挡事件 **。
如果后面的例子应用事件捕捉,则点击 <div>
元素会以下列程序触发 click 事件:
(1) document
(2) <html>
(3) <body>
(4) <div>
** 因为旧版本浏览器不反对,因而理论当中简直不会应用事件捕捉。通常倡议应用事件冒泡,非凡情
况下能够应用事件捕捉。**
1.3 Dom 事件流 (把握)
DOM2 Events 标准规定事件流分为 3 个阶段:事件捕获、达到目标、事件冒泡。
第一步:事件捕获最先产生,为提前拦挡事件提供可能。第二部:理论的指标元素接管到事件。第三步:最初一个阶段是冒泡,最迟要在这个阶段响应事件。以下面那个 HTML 为例:点击 <div>
元素会以如下图 所示的程序触发事件。
==** 在 DOM 事件流中,理论的指标(<div>
元素)在捕捉阶段不会接管到事件。这是因为捕捉阶段从
document 到 <html>
再到 <body>
就完结了。**== 下一阶段,即会在 <div>
元素上触发事件的“达到指标”
阶段,通常在事件处理时被认为是冒泡阶段的一部分(稍后探讨)。而后,冒泡阶段开始,事件反向传
播至文档。
大多数反对 DOM 事件流的浏览器实现了一个小小的拓展。尽管 DOM2 Events 标准明确捕捉阶段不
命中事件指标,==** 但古代浏览器都会在捕捉阶段在事件指标上触发事件。最终后果是在事件指标上有两个
机会来处理事件。**==
留神:留神 所有古代浏览器都反对 DOM 事件流,只有 IE8 及更早版本不反对。
2. 事件处理程序
事件意味着用户或浏览器执行的某种动作。比方,单击(click)、加载(load)、鼠标悬停
(mouseover)。为响应事件而调用的函数被称为事件处理程序(或事件监听器)。事件处理程序的名字
以 “on” 结尾,因而 click 事件的处理程序叫作 onclick,而 load 事件的处理程序叫作 onload。有
很多形式能够指定事件处理程序。
2.1 HTML 事件处理程序(理解)
特定元素反对的每个事件的代码都能够像 HTML 属性一样的写法。此时属性
的值必须是可能执行的 JavaScript 代码。
例如:
<input type="button" value="Click Me" onclick="console.log('Clicked')"/>
留神:因为属性的值是 JavaScript 代码,所以必须要先通过本义 HTML 语法字符能力应用,比方和号(&)、双引号(”)、小于号(<)和大于号(>)。
- 在 HTML 中定义的事件处理程序能够调用在页面其余中央定义的脚本:
<script>
function showMessage() {console.log("Hello world!");
}
</script>
<input type="button" value="Click Me" onclick="showMessage()"/>
- 作为事件处理程序执行的代码能够拜访全局作用域中的所有。
以这种形式指定的事件处理程序, 首先,会创立一个函数来封装属性的值。这个
函数有一个非凡的局部变量 event
,其中保留的就是 event
对象
<!-- 输入 "click" -->
<input type="button" value="Click Me" onclick="console.log(event.type)">
- 在上面这个函数中,this 值相当于事件的指标元素:
<!-- 输入 "Click Me" -->
<input type="button" value="Click Me" onclick="console.log(this.value)">
- ** 这个动态创建的函数的用域链被扩大了。在这个函数中,
document 和元素本身的成员都能够被当成局部变量来拜访 **
这意味着事件处理程序能够更不便地拜访本人的属性。例如:```
<!-- 输入 "Click Me" -->
<input type="button" value="Click Me" onclick="console.log(value)">
```
如果这个元素是一个表单输入框,则作用域链中还会蕴含表单元素,事件处理程序对应的函数等价
于如下这样:```html
<form method="post">
<input type="text" name="username" value="">
<input type="button" value="Echo Username" onclick="console.log(username.value)">
</form>
```
在 HTML 中指定事件处理程序有一些问题:
-
机会问题
有可能 HTML 元素曾经显示
在页面上,用户都与其交互了,而事件处理程序的代码还无奈执行,这样就会产生谬误,解决办法:
大多数 HTML 事件处理程序会封装在 try / catch 块中,
以便在这种状况下静默失败,如上面的例子所示:<input type="button" value="Click Me" onclick="try{showMessage();}catch(ex) {}">
- 浏览器兼容问题
对事件处理程序作用域链的扩大在不同浏览器中可能导致不同的后果
- 应用 HTML 指定事件处理程序的最初一个问题是 HTML 与 JavaScript 强耦合
所以:==** 很多开发者不应用 HTML
事件处理程序,而应用 JavaScript 指定事件处理程序 **==
2.2 DOM0 事件处理程序(把握)
在 JavaScript 中指定事件处理程序的传统形式是把一个函数赋值给(DOM 元素的)一个事件处理程
序属性。
写法如下:
let btn = document.getElementById("myBtn");
btn.onclick = function() {console.log("Clicked");
};
事件处理程
序会在元素的作用域中运行,即 this 等于元素。上面的例子演示了应用 this 援用元素自身:
let btn = document.getElementById("myBtn");
btn.onclick = function() {console.log(this.id); // "myBtn"
};
** 以这种形式增加事件处理程序是注册在事件流的
冒泡阶段的。**
通过将事件处理程序属性的值设置为 null,能够移除通过 DOM0 形式增加的事件处理程序,如下
面的例子所示:
btn.onclick = null;
// 把事件处理程序设置为 null,再点击按钮就不会执行任何操作了。
** 留神:如果事件处理程序是在 HTML 中指定的,则 onclick 属性的值是一个包装相应
HTML 事件处理程序属性值的函数。这些事件处理程序也能够通过在 JavaScript 中将相应
属性设置为 null 来移除。**
2.3 DOM2 事件处理程序(把握)
DOM2 Events 为事件处理程序的赋值和移除定义了两个办法:addEventListener()
和 removeEventListener()
, 这两个办法裸露在所有 DOM 节点上,他们 接管 3 个参数 : 事件名 、 事件处理函数 和一个布尔值 ,true 示意在捕捉阶段调用事件处理函数,false(默认值)示意在冒泡阶段调用事件处理程序
例如:
let btn = document.getElementById("myBtn");
btn.addEventListener("click", () => {console.log(this.id);
}, false);
应用 DOM2
形式的次要劣势是能够为同一个事件增加多个事件处理程序:
let btn = document.getElementById("myBtn");
btn.addEventListener("click", () => {console.log(this.id);
}, false);
btn.addEventListener("click", () => {console.log("Hello world!");
}, false);
多个事件处理程序以增加程序来触发 ,因而后面的代码会先
打印元素 ID,而后显示音讯“Hello world!”。
== 通过 addEventListener() 增加的事件处理程序只能应用 removeEventListener() 并传入与添
加时同样的参数来移除。这意味着应用 addEventListener() 增加的匿名函数无奈移除 ==
大多数状况下,事件处理程序会被增加到事件流的冒泡阶段,次要起因是跨浏览器兼容性好。把事
件处理程序注册到捕捉阶段通常用于在事件达到其指定指标之前拦挡事件。如果不须要拦挡,则不要使
用事件捕捉。
2.4 IE 事件处理程序(理解)
IE 实现了与 DOM 相似的办法,即 attachEvent() 和 detachEvent()。这两个办法接管两个同样
的参数:事件处理程序的名字和事件处理函数。因为 IE8 及更早版本只反对事件冒泡,所以应用
attachEvent() 增加的事件处理程序会增加到冒泡阶段。详情参考 (红宝书第四版 497 页)
2.5 跨浏览器事件处理程序(理解)
本人编写跨浏览
器事件处理代码也很简略,次要依赖能力检测。要确保事件处理代码具备最大兼容性,只须要让代码在
冒泡阶段运行即可。详情可参考 (红宝书第四版 498 页)
3. 事件对象
在 DOM 中产生事件时,所有相干信息都会被收集并存储在一个名为 event 的对象中。这个对象包
含了一些根本信息,比方导致事件的元素、产生的事件类型,以及可能与特定事件相干的任何其余数据。
例如,鼠标操作导致的事件会生成鼠标地位信息,而键盘操作导致的事件会生成与被按下的键无关的信
息。所有浏览器都反对这个 event 对象,只管反对形式不同。
3.1 DOM 对象事件(了解)
在 DOM 合规的浏览器中,event
对象是传给事件处理函数的惟一参数。不论以哪种形式(DOM0 或者 DOM2)指定事件处理程序,都会传入这个 event
对象。
上面的例子展现了在两种形式下都能够使
用事件对象:
let btn = document.getElementById("myBtn");
btn.onclick = function(event) {console.log(event.type); // "click"
};
btn.addEventListener("click", (event) => {console.log(event.type); // "click"
}, false);
在通过 HTML 属性指定的事件处理程序中,同样能够应用变量 event 援用事件对象。例如:
<input type="button" value="Click Me" onclick="console.log(event.type)">
如前所述,事件对象蕴含与特定事件相干的属性和办法。不同的事件生成的事件对象也会蕴含不同
的属性和办法。不过,所有事件对象都会蕴含下表列出的这些公共属性和办法。(本文只列举了上面几个公共属性,更多公共参数具体可参考《红宝书第四版 500 页》)
属性 / 办法 | 类 型 | 读 / 写 | 阐明 |
---|---|---|---|
bubbles | 布尔值 | 只读 | 示意事件是否冒泡 |
currentTarget | 元素 | 只读 | 以后事件处理程序所在的元素 |
eventPhase | 整数 | 只读 | 示意调用事件处理程序的阶段:1 代表捕捉阶段,2 代表达到指标,3 代表冒泡阶段 |
stopPropagation() | 函数 | 只读 | 用于勾销所有后续事件捕捉或事件冒泡。只有 bubbles 为 true 才能够调用这个办法 |
target | 元素 | 只读 | 事件指标 |
type | 字符串 | 只读 | 被触发的事件类型 |
在事件处理程序外部,this 对象始终等于 currentTarget 的值,而 target 只蕴含事件的理论
指标。如果事件处理程序间接增加在了用意的指标,则 this、currentTarget 和 target 的值是一样
的。上面的例子展现了这两个属性都等于 this 的情景:
let btn = document.getElementById("myBtn");
btn.onclick = function(event) {console.log(event.currentTarget === this); // true
console.log(event.target === this); // true
};
如果这个事件处理程序是增加到按钮的父节点(如 document.body)上,
那么它们的值就不一样了。例如:
document.body.onclick = function(event) {console.log(event.currentTarget === document.body); // true
console.log(this === document.body); // true
console.log(event.target === document.getElementById("div")); // true
console.log(event.currentTarget === event.target)
};
** 这种状况下点击按钮,==this== 和 ==currentTarget== 都等于 document.body,这是因为 == 它是注册事件
处理程序的元素 ==。== 而 target 属性等于按钮自身,这是因为那才是 click 事件真正的指标, target 属性等于触发事件的文档中最深的节点 ==。因为按钮
自身并没有注册事件处理程序,因而 click 事件冒泡到 document.body,从而触发了在它下面注册的
处理程序。**
type 属性在一个处理程序解决多个事件时很有用。比方上面的处理程序中就应用了 event.type:
let btn = document.getElementById("myBtn");
let handler = function(event) {switch(event.type) {
case "click":
console.log("Clicked");
break;
case "mouseover":
event.target.style.backgroundColor = "red";
break;
case "mouseout":
event.target.style.backgroundColor = "";
break;
}
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
留神:event 对象只在事件处理程序执行期间存在,一旦执行结束,就会被销毁。
3.2 IE 事件对象(理解)
与 DOM 事件对象不同,IE 事件对象能够基于事件处理程序被指定的形式以不同形式来拜访。
- ** 如果
事件处理程序是应用 DOM0 形式指定的,则 event 对象只是 window 对象的一个属性 **
- ** 如果是应用 HTML 属性形式指定的事件处理程序,则 event 对象同样能够通过变量 event 拜访(与
DOM 模型一样)**。
详情请参考(红宝书第四版 502 页)
3.3 跨浏览器事件(理解)
本文简洁只是简洁的形容,具体可参考(红宝书第四版 505 页)
尽管 DOM 和 IE 的事件对象并不相同,但它们有足够的相似性能够实现跨浏览器计划。
DOM 事件对象中蕴含 IE 事件对象的所有信息和能力,只是模式不同。这些共性可让两种事件模型之间的映射成
为可能。
var EventUtil = {addHandler: function(element, type, handler) {// 为节俭版面,删除了之前的代码。具体的代码可参考(红宝书 498 页)
},
getEvent: function(event) {return event ? event : window.event;},
getTarget: function(event) {return event.target || event.srcElement;},
preventDefault: function(event) {if (event.preventDefault) {event.preventDefault();
} else {event.returnValue = false;}
},
removeHandler: function(element, type, handler) {// 为节俭版面,删除了之前的代码。具体的代码可参考(红宝书 498 页)
},
stopPropagation: function(event) {if (event.stopPropagation) {event.stopPropagation();
} else {event.cancelBubble = true;}
}
};
下
面是应用 EventUtil 中这个办法对立获取 event 对象的一个例子:
btn.onclick = function(event) {event = EventUtil.getEvent(event);
};
4. 事件类型(把握)
DOM3 Events 定义了如下事件类型。
- 用户界面事件(
UIEvent
):波及与 BOM 交互的通用浏览器事件。 - 焦点事件(
FocusEvent
):在元素取得和失去焦点时触发。 - 鼠标事件(
MouseEvent
):应用鼠标在页面上执行某些操作时触发。 - 滚轮事件(
WheelEvent
):应用鼠标滚轮(或相似设施)时触发。 - 输出事件(
InputEvent
):向文档中输出文本时触发。 - 键盘事件(
KeyboardEvent
):应用键盘在页面上执行某些操作时触发。 - 合成事件(
CompositionEvent
):在应用某种 IME(Input Method Editor,输入法编辑器)输出
字符时触发。
4.1 用户界面事件(把握)
==** 重点:晓得了 img 元素能够触发 load 事件、error 事件。
晓得了 resize 事件、scroll 事件在不同浏览器中的差别,以及解决办法 **==
用户界面事件或 UI 事件不肯定跟用户操作无关。这类事件在 DOM 标准呈现之前就曾经以某种形
式存在了,保留它们是为了向后兼容。UI 事件次要有以下几种。
- <font color=”red”>
DOMActivate
</font>:元素被用户通过鼠标或键盘操作激活时触发(比 click 或 keydown 更通用)。
这个事件在 DOM3 Events 中曾经废除。因为浏览器实现之间存在差别,所以不要应用它。
load
:在 window 受骗页面加载实现后触发,在窗套(<frameset>)受骗所有窗格(<frame>)
都加载实现后触发,在 <img>
元素受骗图片加载实现后触发,在 <object>
元素受骗相应对象加
载实现后触发。
unload
:在 window 受骗页面齐全卸载后触发,在窗套受骗所有窗格都卸载实现后触发,在
<object>
元素受骗相应对象卸载实现后触发。
abort
:在<object>
元素受骗相应对象加载实现前被用户提前终止下载时触发。error
:在 window 受骗 JavaScript 报错时触发,在<img>
元素受骗无奈加载指定图片时触发,
在 <object>
元素受骗无奈加载相应对象时触发,在窗套受骗一个或多个窗格无奈实现加载时
触发。
select
:在文本框(<input>
或 textarea)受骗用户抉择了一个或多个字符时触发。resize
:在 window 或窗格受骗窗口或窗格被缩放时触发。scroll
:当用户滚动蕴含滚动条的元素时在元素上触发。<body> 元素蕴含已加载页面的滚动条。
大多数 HTML 事件与 window 对象和表单控件无关。
- load 事件
能够用 load 事件实现图片预加载具体可参考(红宝书第四版)
window.addEventListener("load", () => {let image = new Image();
image.addEventListener("load", (event) => {console.log("Image loaded!");
});
image.src = "smile.gif";
});
这里调用 Image 构造函数创立了一个新图片,并给它设置了事件处理程序。有些浏览器会把 Image
对象实现为 <img>
元素,但并非所有浏览器都如此。所以最好把它们看成是两个货色。
- unload 事件
与 load 事件绝对的是 unload 事件,unload 事件会在文档卸载实现后触发。unload 事件 个别是
在从一个页面导航到另一个页面时触发,最罕用于清理援用,以防止内存透露。
- resize 事件
当浏览器窗口被缩放到新高度或宽度时,会触发 resize 事件。这个事件在 window 上触发,因而
能够通过 JavaScript 在 window 上或者为 <body> 元素增加 onresize 属性来指定事件处理程序。优先使
用 JavaScript 形式:
window.addEventListener("resize", (event) => {console.log("Resized");
});
** 不同浏览器在决定何时触发 resize 事件上存在重要差别。无论如何,都应该防止在这个事件处理程序中执行过多
计算。否则可能因为执行过于频繁而导致浏览器响应明确变慢。**
留神:浏览器窗口在最大化和最小化时也会触发 resize 事件。
- scroll 事件
尽管 scroll 事件产生在 window 上,但实际上反映的是页面中相应元素的变动。在不同浏览器中有差别。上面的代码演示了如何解决差别:(具体可参考 红宝书第四版 509 页)
window.addEventListener("scroll", (event) => {if (document.compatMode == "CSS1Compat") {console.log(document.documentElement.scrollTop);
} else {console.log(document.body.scrollTop);
}
});
4.2 焦点事件
焦点事件在页面元素取得或失去焦点时触发。这些事件能够与 document.hasFocus() 和
document.activeElement 一起为开发者提供用户在页面中导航的信息。焦点事件有以下 6 种。
blur
:当元素失去焦点时触发。这个事件不冒泡,所有浏览器都反对。- <font color=”red”>
DOMFocusIn
</font>:当元素取得焦点时触发。这个事件是 focus 的冒泡版。Opera 是惟一反对这个事
件的支流浏览器。DOM3 Events 废除了 DOMFocusIn,举荐 focusin。
- <font color=”red”>
DOMFocusOut
</font>:当元素失去焦点时触发。这个事件是 blur 的通用版。Opera 是惟一反对这个事
件的支流浏览器。DOM3 Events 废除了 DOMFocusOut,举荐 focusout。
focus
:当元素取得焦点时触发。这个事件 不冒泡,所有浏览器都反对focusin
:当元素取得焦点时触发。这个事件是 focus 的冒泡版focusout
:当元素失去焦点时触发。这个事件是 blur 的通用版。
焦点事件中的两个次要事件是 focus 和 blur,这两个事件在 JavaScript 晚期就失去了浏览器反对。
它们最大的问题是不冒泡。这导致 IE 起初又减少了 focusin 和 focusout,IE 新增的这两个事件曾经被 DOM3 Events 标准化。
当焦点从页面中的一个元素移到另一个元素上时,会 == 顺次产生 == 如下事件。
(1) focuscout
在失去焦点的元素上触发。
(2) focusin
在取得焦点的元素上触发。
(3) blur
在失去焦点的元素上触发。
(4) DOMFocusOut
在失去焦点的元素上触发。
(5) focus
在取得焦点的元素上触发。
(6) DOMFocusIn
在取得焦点的元素上触发。
其中,blur、DOMFocusOut 和 focusout 的事件指标是失去焦点的元素,而 focus、DOMFocusIn
和 focusin 的事件指标是取得焦点的元素。
4.3 鼠标和滚轮事件
DOM3 Events
鼠标是用户的次要定位设施。DOM3 Events 定义了 9 种鼠标事件。
click
:在用户单击鼠标主键(通常是左键)或按键盘回车键时触发。这次要是基于无障碍的考
虑,让键盘和鼠标都能够触发 onclick 事件处理程序。
dblclick
:在用户双击鼠标主键(通常是左键)时触发。这个事件不是在 DOM2 Events 中定义
的,但失去了很好的反对,DOM3 Events 将其进行了标准化。
mousedown
:在用户按下任意鼠标键时触发。这个事件不能通过键盘触发。mouseenter
:在用户把鼠标光标从元素内部移到元素外部时触发。这个事件 不冒泡,也不会在
光标通过后辈元素时触发。mouseenter 事件不是在 DOM2 Events 中定义的,而是 DOM3 Events
中新增的事件。
mousemove
:在鼠标光标在元素上挪动时重复触发。这个事件不能通过键盘触发。mouseout
:在用户把鼠标光标从一个元素移到另一个元素上时触发。移到的元素能够是原始元
素的内部元素,也能够是原始元素的子元素。这个事件不能通过键盘触发。
mouseover
:在用户把鼠标光标从元素内部移到元素外部时触发。这个事件不能通过键盘触发。mouseup
:在用户开释鼠标键时触发。这个事件不能通过键盘触发。
** 页面中的所有元素都反对鼠标事件。除了 mouseenter 和 mouseleave,所有鼠标事件都会冒泡,
都能够被勾销,而这会影响浏览器的默认行为。**
因为事件之间存在关系,因而勾销鼠标事件的默认行为也会影响其余事件。
例如:如果 mousedown 和 mouseup 中的任意一个事件被勾销,那么 click 事件就不会触发。
这 4 个事件永远会依照如下程序触发:
(1) mousedown
(2) mouseup
(3) click
(4) mousedown
(5) mouseup
(6) click
(7) dblclick
click 和 dblclick 在触发前都依赖其余事件触发,mousedown 和 mouseup 则不会受其余事件影响。
IE8 及更早版本的实现中有个问题,这会导致双击事件跳过第二次 mousedown 和 click 事件。相
应的程序变成了:
(1) mousedown
(2) mouseup
(3) click
(4) mouseup
(5) dblclick
鼠标事件还有一个名为滚轮事件的子类别。滚轮事件只有一个事件 mousewheel
,反映的是鼠标滚
轮或带滚轮的相似设施上滚轮的交互。
本大节以下详情内容可查看红宝书
- 客户端坐标(红宝书第四版 511 页)
- 页面坐标(红宝书第四版 512页)
- 屏幕坐标(红宝书第四版 513 页)
鼠标事件不仅是在浏览器窗口中产生的,也是在整个屏幕上产生的。能够通过 event 对象的
screenX 和 screenY 属性获取鼠标光标在屏幕上的坐标。下图 展现了浏览器中触发鼠标事件的光标
的屏幕坐标。
能够像上面这样获取鼠标事件的屏幕坐标:
let div = document.getElementById("myDiv");
div.addEventListener("click", (event) => {console.log(`Screen coordinates: ${event.screenX}, ${event.screenY}`);
});
- 润饰键(红宝书第四版 514 页)
尽管鼠标事件次要是通过鼠标触发的,但有时候要确定用户想实现的操作,还要思考键盘按键的状
态。键盘上的润饰键 Shift、Ctrl、Alt 和 Meta 常常用于批改鼠标事件的行为。DOM 规定了 4 个属性来表
示这几个润饰键的状态:shiftKey、ctrlKey、altKey 和 metaKey。这几属性会在各自对应的润饰
键被按下时蕴含布尔值 true,没有被按下时蕴含 false。在鼠标事件产生的,能够通过这几个属性来
检测润饰键是否被按下。
- 相干元素(红宝书第四版 514 页)
只有在元素上单击鼠标主键(或按下键盘上的回车键)时 click 事件才会触发,因而按键信息并
不是必须的。对 mousedown 和 mouseup 事件来说,event 对象上会有一个 button 属性,示意按下或
开释的是哪个按键。DOM 为这个 button 属性定义了 3 个值:0 示意鼠标主键、1 示意鼠标中键(通常
也是滚轮键)、2 示意鼠标副键。依照常规,鼠标主键通常是右边的按键,副键通常是左边的按键。
- 鼠标按键(红宝书第四版 516 页)
- 额定事件信息(红宝书第四版 516 页)
- mousewheel 事件(红宝书第四版 516 页)
- 触摸屏设施(红宝书第四版 517 页)
iOS 和 Android 等触摸屏设施的实现天壤之别,因为触摸屏通常不反对鼠标操作。在为触摸屏设施
开发时,要记住以下事项。
- 不反对 dblclick 事件。双击浏览器窗口能够放大,但没有方法笼罩这个行为。
- ** 单指导触屏幕上的可点击元素会触发 mousemove 事件。如果操作会导致内容变动,则不会再触
发其余事件。如果屏幕上没有变动,则会相继触发 mousedown、mouseup 和 click 事件。点
触不可点击的元素不会触发事件。可点击元素是指导击时有默认动作的元素(如链接)或指定
了 onclick 事件处理程序的元素。**
- mousemove 事件也会触发 mouseover 和 mouseout 事件。
- 双指导触屏幕并滑动导致页面滚动时会触发 mousewheel 和 scroll 事件。
- 无障碍问题(红宝书第四版 517 页)
4.4 键盘与输出事件
键盘事件蕴含 3 个事件:
keydown
,用户按下键盘上某个键时触发,而且继续按住会反复触发。keypress
,用户按下键盘上某个键并产生字符时触发,而且继续按住会反复触发。Esc 键也会
触发这个事件。DOM3 Events 废除了 keypress 事件,而举荐 textInput 事件。
keyup
,用户开释键盘上某个键时触发。
** 这里 keydown 和 keypress 事件会在文本框呈现变动之前触发,而 keyup
事件会在文本框呈现变动之后触发。如果一个字符键被按住不放,keydown 和 keypress 就会反复触
发,直到这个键被开释。**
留神:** 键盘事件反对与鼠标事件雷同的润饰键。shiftKey、ctrlKey、altKey 和 metaKey
属性在键盘事件中都是可用的。IE8 及更早版本不反对 metaKey 属性。**
- DOM3 的变动
只管所有浏览器都实现了某种模式的键盘事件,DOM3 Events 还是做了一些批改。比方,DOM3
Events 标准并未规定 charCode 属性,而是定义了 key 和 char 两个新属性。
其中,key 属性用于代替 keyCode,且蕴含字符串。在按下字符键时,key 的值等于文本字符(如
“k”或“M”);在按下非字符键时,key 的值是键名(如“Shift”或“ArrowDown”)。char 属性在按
下字符键时与 key 相似,在按下非字符键时为 null。
==因为不足跨浏览器反对,因而不倡议应用 key、keyIdentifier、和 char。==
==**DOM 和 IE 的 event 对
象都反对 keyCode 属性。**==
一旦有了字母编码,就能够应用 String.fromCharCode()
办法将其转换为理论的字符了。
window.addEventListener("keypress", (event) => {console.log( String.fromCharCode(event.keyCode));
});
本大节从 4.textInput 当前的内容理解即可
- textInput 事件(红宝书第四版 521 页)
DOM3 Events 标准减少了一个名为 textInput 的事件,其在字符被输出到可编辑区域时触发。作
为对 keypress 的代替,textInput 事件的行为有些不一样。一个区别是 keypress 会在任何能够获
得焦点的元素上触发,而 textInput 只在可编辑区域上触发。另一个区别是 textInput 只在有新字
符被插入时才会触发,而 keypress 对任何可能影响文本的键都会触发(包含退格键)。
- 设施上的键盘事件(红宝书第四版 522 页)
任天堂 Wii 会在用户按下 Wii 遥控器上的键时触发键盘事件。尽管不能拜访 Wii 遥控器上所有的键,
但其中一些键能够触发键盘事件
4.5 合成事件(理解即可)
合成事件是 DOM3 Events 中新增的,用于解决通常应用 IME 输出时的简单输出序列。
4.6 <font color=”red”> 变动事件 </font>(已废除)
这些事件曾经被废除,浏览器曾经在有打算地进行对它们的反对。变动事件曾经被
Mutation Observers 所取代
4.7 HTML5 事件(临时理解即可,前面必须晓得)
DOM 标准并未涵盖浏览器都反对的所有事件。很多浏览器依据特定的用户需要或应用场景实现了
自定义事件。HTML5 详尽地列出了浏览器反对的所有事件。本节探讨 HTML5 中失去浏览器较好反对
的一些事件。留神这些并不是浏览器反对的所有事件。
-
contextmenu 事件
Windows 95 通过单击鼠标右键为 PC 用户减少了上下文菜单的概念。不久,这个概念也在 Web 上得
以实现。contextmenu 事件冒泡,因而只有给 document 指定一个事件处理程序就能够解决页面上的所有
同类事件。
这个事件在所有浏览器中都能够勾销,在 DOM 合规的浏览器
中应用 event.preventDefault(),在 IE8 及更早版本中将 event.returnValue 设置为 false。contextmenu 事件应该算一种鼠标事件,因而 event 对象上的很多属性都与光标地位无关。通常,自
定义的上下文菜单都是通过 oncontextmenu 事件处理程序触发显示,并通过 onclick 事件处理程序
触发暗藏的。来看上面的例子:<!DOCTYPE html> <html> <head> <title>ContextMenu Event Example</title> </head> <body> <div id="myDiv">Right click or Ctrl+click me to get a custom context menu. Click anywhere else to get the default context menu.</div> <ul id="myMenu" style="position:absolute;visibility:hidden;background-color: silver"> <li><a href="http://www.somewhere.com"> somewhere</a></li> <li><a href="http://www.wrox.com">Wrox site</a></li> <li><a href="http://www.somewhere-else.com">somewhere-else</a></li> </ul> </body> <script> window.addEventListener("load", (event) => {let div = document.getElementById("myDiv"); div.addEventListener("contextmenu", (event) => {event.preventDefault(); let menu = document.getElementById("myMenu"); menu.style.left = event.clientX + "px"; menu.style.top = event.clientY + "px"; menu.style.visibility = "visible"; }); document.addEventListener("click", (event) => {document.getElementById("myMenu").style.visibility = "hidden"; }); }); </script> </html>
当鼠标点击右键就会呈现这样的成果,相似于在 windows 桌面上点击右键弹出的菜单:
-
beforeunload
事件beforeunload 事件会在 window 上触发,用意是给开发者提供阻止页面被卸载的机会。这个事件
会在页面行将从浏览器中卸载时触发,如果页面须要持续应用,则能够不被卸载。
这个事件会向用户显示一个确认框,其中的消
息表明浏览器行将卸载页面,并请用户确认是心愿敞开页面,还是持续留在页面上,如图:实现上图的代码:
window.addEventListener("beforeunload", (event) => { let message = "I'm really going to miss you if you go."; event.returnValue = message; return message; });
-
DOMContentLoaded 事件
**window 的 load 事件会在页面齐全加载后触发,因为要期待很多内部资源加载实现,所以会破费
较长时间。而 DOMContentLoaded 事件会在 DOM 树构建实现后立刻触发,而不必期待图片、JavaScript
文件、CSS 文件或其余资源加载实现 **。绝对于 load 事件,DOMContentLoaded 能够让开发者在内部资
源下载的同时就能指定事件处理程序,从而让用户可能更快地与页面交互。要解决 DOMContentLoaded 事件,须要给 document 或 window 增加事件处理程序(理论的事件
指标是 document,但会冒泡到 window)。document.addEventListener("DOMContentLoaded", (event) => {console.log("Content loaded"); });
DOMContentLoaded 事件的 event 对象中不蕴含任何额定信息(除了 target 等于 document)。
**DOMContentLoaded 事件通常用于增加事件处理程序或执行其余 DOM 操作。这个事件始终在 load
事件之前触发 **。对于不反对 DOMContentLoaded 事件的浏览器,能够应用超时为 0 的 setTimeout() 函数,通过
其回调来设置事件处理程序,比方:setTimeout(() => {// 在这里增加事件处理程序}, 0);
** 思考到各种影响因素,以上代码不肯定保障能在 load 事
件之前执行超时回调。** - readystatechange 事件(红宝书第四版 525 页)
这个有点神秘的事件旨在提供文档或元素加载状态的信息,但行为有时候并不稳固。
** 留神 应用 readystatechange 只能尽量模仿 DOMContentLoaded,但做不到分毫不差。
load 事件和 readystatechange 事件产生的程序在不同页面中是不一样的。** - pageshow 与 pagehide 事件(红宝书第四版 527 页)
Firefox 和 Opera 开发了一个名为往返缓存(bfcache,back-forward cache)的性能,此性能旨在应用
浏览器“后退”和“后退”按钮时放慢页面之间的切换。Firefx 决定提供一些事件,把往返缓存的行为裸露进去。
-
hashchange 事件
HTML5 减少了 hashchange 事件,用于在 URL 散列值(URL 最初 # 前面的局部)发生变化时告诉
开发者。这是因为开发者常常在 Ajax 应用程序中应用 URL 散列值存储状态信息或路由导航信息。onhashchange 事件处理程序必须增加给 window,每次 URL 散列值发生变化时会调用它。
event
对象有两个新属性:oldURL 和 newURL。这两个属性别离保留变动前后的 URL,而且是蕴含散列值的
残缺 URL。上面的例子展现了如何获取变动前后的 URL:window.addEventListener("hashchange", (event) => {console.log(`Old URL: ${event.oldURL}, New URL: ${event.newURL}`); });
如果想确定以后的散列值,最好应用 location 对象:
window.addEventListener("hashchange", (event) => {console.log(`Current hash: ${location.hash}`); });
4.8 设施事件(理解)(红宝书第四版 528 页)
随着智能手机和平板计算机的呈现,用户与浏览器交互的新形式应运而生。为此,一批新事件被发
明了进去。设施事件能够用于确定用户应用设施的形式。W3C 在 2011 年就开始起草一份新标准,用于
定义新设施及设施相干的事件。
orientationchange
事件
苹果公司在挪动 Safari 浏览器上发明了 orientationchange 事件,以不便开发者判断用户的设施
是处于垂直模式还是程度模式。deviceorientation
事件(红宝书第四版 529 页)devicemotion
事件(红宝书第四版 531 页)
4.9 触摸及手势事件(理解)
Safari 为 iOS 定制了一些专有事件,以不便开发者。因为 iOS 设施没有鼠标和键盘,所以惯例的鼠
标和键盘事件不足以创立具备残缺交互能力的网页。同时,WebKit 也为 Android 定制了很多专有事件,
成为了事实标准,并被纳入 W3C 的 Touch Events 标准。本节介绍的事件只实用于触屏设施。
-
触摸事件
触摸事件有如下几种:
touchstart
:手指放到屏幕上时触发(即便有一个手指曾经放在了屏幕上)。touchmove
:手指在屏幕上滑动时间断触发。在这个事件中调用 preventDefault() 能够阻止滚动。touchend
:手指从屏幕上移开时触发。touchcancel
:零碎进行跟踪触摸时触发。文档中并未明确什么状况下进行跟踪。
** 这些事件都会冒泡,也都能够被勾销。只管触摸事件不属于 DOM 标准,但浏览器依然以兼容 DOM
的形式实现了它们。因而,每个触摸事件的 event 对象都提供了鼠标事件的公共属性:bubbles、
cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、
ctrlKey 和 metaKey。**除了这些公共的 DOM 属性,触摸事件还提供了以下 3 个属性用于跟踪触点。
touches
:Touch 对象的数组,示意以后屏幕上的每个触点。targetTouches
:Touch 对象的数组,示意特定于事件指标的触点。changedTouches
:Touch 对象的数组,示意自上次用户动作之后变动的触点。
每个 Touch 对象都蕴含下列属性。
clientX
:触点在视口中的 x 坐标。clientY
:触点在视口中的 y 坐标。identifier
:触点 ID。pageX
:触点在页面上的 x 坐标。pageY
:触点在页面上的 y 坐标。screenX
:触点在屏幕上的 x 坐标。screenY
:触点在屏幕上的 y 坐标。target
:触摸事件的事件指标。
当手指点触屏幕上的元
素时,顺次会产生如下事件(包含鼠标事件):
(1)touchstart
(2)
mouseover
(3)
mousemove
(1 次)(4)
mousedown
(5)
mouseup
(6)
click
(7)
touchend
-
手势事件(红宝书第四版 533 页)
iOS 2.0 中的 Safari 还减少了一种手势事件。手势事件会在两个手指触碰屏幕且绝对间隔或旋转角度
变动时触发。手势事件有以下 3 种。gesturestart
:一个手指曾经放在屏幕上,再把另一个手指放到屏幕上时触发。gesturechange
:任何一个手指在屏幕上的地位发生变化时触发。gestureend
: 其中一个手指来到屏幕时触发。
** 留神 触摸事件也会返回 rotation 和 scale 属性,但只在两个手指触碰屏幕时才会变
化。一般来说,应用两个手指的手势事件比思考所有交互的触摸事件应用起来更容易一些。**
事件参考(红宝书第四版 534 页)
本节给出了 DOM 标准、HTML5 标准,以及概述事件行为的其余以后已公布标准中定义的所有浏
览器事件。这些事件依照 API 和 / 或标准分类。
5. 内存于性能