JavaScript与HTML的交互是经过事件实现的,事件表明文档或浏览器窗口中某个有意义的时刻。javascript
可使用仅在事件发生时执行的监听器(即处理程序)订阅事件。=>观察者模式 => 页面行为(JavaScript中定义)与页面展现(HTML和CSS定义)的分离。html
最先的事件是为了把某些表单处理工做从服务器转移到浏览器上来。DOM2开始尝试以符合逻辑的方式来标准化DOM事件。IE8是最后一个使用专有事件系统的主流浏览器。java
页面哪一个部分拥有特定的事件呢?当你点击一个按钮时,实际上不光点击了这个按钮,还点击了它的容器以及整个页面。数组
事件流描述了页面接收事件的顺序。浏览器
IE支持事件冒泡流,Netscape Communicator支持事件捕获流缓存
从最具体的元素开始触发,而后向上传播至没有那么具体的元素(document)。安全
点击事件:被点击的元素最早触发click事件,而后click事件沿DOM树一路向上,在通过的每一个节点上依次触发,直至到达document对象。服务器
现代浏览器中的事件会一直冒泡到window对象。编辑器
最不具体的节点(document)最早收到事件,而最具体的节点最后收到事件。=>为了在事件到达最终目标前拦截事件。ide
点击事件:最早由document元素捕获,而后沿DOM树依次向下传播,直至到达实际的目标元素。
现代浏览器都是从window对象开始捕获事件。DOM2 Events规范规定的是从document开始。
因为旧版本浏览器不支持,一般建议使用事件冒泡,特殊状况下可使用事件捕获。
DOM2 Events规范规定事件流分为3个阶段:事件捕获、到达目标和事件冒泡。
在DOM事件流中,实际的目标在捕获阶段不会接收到事件。下一阶段会在实际目标元素上触发事件的“到达目标”阶段,一般在事件处理时被认为是冒泡阶段的一部分;而后冒泡阶段开始,事件反向传播至文档。
虽然DOM2 Events规范明确捕获阶段不命中事件目标,但现代浏览器都会在捕获阶段在事件目标上触发事件。=> 在事件目标上有两个机会来处理事件。
全部现代浏览器都支持DOM事件流,只有IE8及更早版本不支持。
capture phase | | / \ bubbling up -----------------| |--| |----------------- | element1 | | | | | | -------------| |--| |----------- | | |element2 \ / | | | | | -------------------------------- | | W3C event model | ------------------------------------------
事件是用户或浏览器执行的某种动做。如click、load等。
为响应事件而调用的函数被称为事件处理程序(或事件监听器)。事件处理程序的名字以“on”开头。
有多种方式能够指定事件处理程序。
特定元素支持的每一个事件均可以使用事件处理程序的名字(onxxx)以HTML属性的形式来指定。此时属性的值必须是可以执行的JavaScript代码。
由于属性的值是JavaScript代码,因此不能在未经转义的状况下使用HTML语法字符,如&、"、<和>。为避免使用HTML实体,可使用单引号代替双引号,或者使用\"。
在HTML中定义的事件处理程序能够包含精确的动做指令,也能够调用在页面其余地方定义的脚本。做为事件处理程序执行的代码能够访问全局做用域中的一切。
以这种方式指定的事件处理程序有一些特殊的地方:
这个动态建立的包装函数,其做用域链被扩展了。=> document和元素自身的成员均可以被当成局部变量来访问。这是经过使用with实现的。
// 实际上的包装函数是onclick属性的值 function () { with(document) { with(this) { // ... HTML事件处理程序属性值 } } }
=> 事件处理程序能够更方便地访问本身的属性(不用带this.)
若是元素是一个表单输入框,则做用域链中还会包含表单元素 => 事件处理程序的代码能够没必要引用表单元素,而直接访问同一表单中的其余成员了(经过name属性)。
在HTML中指定事件处理程序存在的问题:
时机问题。有可能HTML元素已经显示在页面上,但事件处理程序的代码还没法执行。=> 大多数HTML事件处理程序会封装在try/catch块中,以便在这种状况下静默失败。
<input type="button" value="Click Me" onclick="try{doSomething();}catch(ex){}">
把一个函数赋值给(DOM元素的)一个事件处理程序属性。=> 简单
要使用JavaScript指定事件处理程序,必须先取得要操做对象的引用。
每一个元素(包括window和document)都有一般小写的事件处理程序属性。
赋值代码运行以后才会给事件处理程序赋值。
所赋函数被视为元素的方法。=> 事件处理程序会在元素的做用域中运行,即this等于元素。
let btn = document.querySelector('#myBtn'); btn.onclick = function() { console.log(this.id); // "myBtn" }
以这种方式添加事件处理程序是注册在事件流的冒泡阶段的。
经过将事件处理程序属性的值设置为null,能够移除经过DOM0方式添加的事件处理程序。(在HTML中指定的事件处理程序,也能够经过JavaScript将相应属性设置为null来移除)
btn.onclick = null;
DOM2 Events为事件处理程序的赋值和移除定义了两个方法:addEventListener()和removeEventListener()。暴露在全部DOM节点上。
接收3个参数:事件名、事件处理函数和一个表示是否在捕获阶段调用处理函数的布尔值(默认值为false,在冒泡阶段调用)。
这个事件处理程序一样在被附加到的元素的做用域中运行:this等于元素。
主要优点:能够为同一个事件添加多个事件处理程序。多个事件处理程序以添加顺序来触发。
经过addEventListener()添加的事件处理程序只能使用removeEventListener()并传入与添加时一样的参数来移除。(事件处理函数必须是同一个)
大多数状况下,事件处理程序会被添加到事件流的冒泡阶段,主要缘由是跨浏览器兼容性好。(除非须要在事件到达其指定目标以前拦截事件)
IE实现了与DOM相似的方法,attachEvent()和detachEvent()。
接收2个参数:事件处理程序的名字和事件处理函数。由于IE8及更早版本只支持事件冒泡,因此使用attachEvent()添加的事件处理程序会添加到冒泡阶段。
在IE中使用attachEvent()与使用DOM0方式的主要区别在于事件处理程序的做用域。使用attachEvent()时,事件处理程序是在全局做用域中运行的,所以this等于window。
attachEvent()方法也能够给一个元素添加多个事件处理程序。以添加它们的顺序反向触发。
使用attachEvent()添加的事件处理程序将使用detachEvent()来移除,只要提供相同的参数(处理函数是相同的函数引用)。
let btn = document.querySelector('#myBtn'); var handler = function() { console.log("Clicked"); }; btn.attachEvent("onclick", handler); btn.detachEvent("onclick", handler);
以跨浏览器兼容的方式处理事件。
本身编写跨浏览器事件处理代码主要依赖能力检测。要确保最大兼容性,只要让代码在冒泡阶段运行便可。
var EventUtil = { addHandler: function(element, type, handler) { if(element.addEventListener) { element.addEventListener(type, handler, false); } else if(element.attachEvent) { element.attachEvent("on"+type, handler); } else { // 默认DOM0方式 element["on"+type] = handler; } }, removeHandler: function(element, type, handler) { if(element.removeEventListener) { element.removeEventListener(type, handler, false); } else if(element.detachEvent) { element.detachEvent("on"+type, handler); } else { // 默认DOM0方式 element["on"+type] = null; } } }; // 使用 let btn = document.querySelector('#myBtn'); let handler = function() { console.log("Clicked"); }; EventUtil.addHandler(btn, "click", handler); EventUtil.removeHandler(btn, "click", handler);
没有解决的存在的问题:
在DOM中发生事件时,全部相关信息(如事件目标元素、事件类型)都会被收集并存储在一个名为event的对象中。
在DOM合规的浏览器中,event对象是传给事件处理程序的惟一参数。无论以哪一种方式(DOM0或DOM2)指定事件处理程序,都会传入这个event对象。在经过HTML属性指定的事件处理程序中,一样可使用变量event引用事件对象。
全部事件对象包含的公共属性和方法:
在事件处理程序内部,this始终等于currentTarget。this === event.currentTarget
。
若是事件处理程序直接添加在乎图的目标,则this、currentTarget和target三者相等。
type属性在一个处理程序处理多个事件时颇有用:根据事件类型,作出不一样的响应。
preventDefault()可阻止特定事件的默认动做,如连接的默认行为是被单击时导航到href属性指定的URL。任何可调用preventDefault()取消默认行为的事件,其event对象的cancelable属性都会设置为true。
stopPropagation()用于当即阻止事件流在DOM结构中传播,取消后续的事件捕获或冒泡。
eventPhase属性可用于肯定事件流当前所处的阶段。若是事件处理程序在目标上被调用,则eventPhase等于2 => 虽然”到达目标“是在冒泡阶段发生的,但eventPhase等于2。=> 当eventPhase等于2,this、currentTarget和target三者相等。
event对象只在事件处理程序执行期间存在,一旦执行完毕,就会被销毁。
IE事件对象能够基于事件处理程序被指定的方式以不一样的方式来访问。
全部IE事件对象都会包含的公共属性和方法:
事件处理程序的做用域取决于指定它的方式,因此更好的方式是使用事件对象的srcElement属性代替this。(DOM0方式下,this等于元素;attachEvent()方式下,this等于window)
与DOM不一样,没法经过JavaScript肯定事件是否能够被取消。
cancelBubble属性与stopPropagation()方法用途类似,但IE8及更早版本不支持捕获阶段,因此只会取消冒泡。
DOM事件对象中包含IE事件对象的全部信息和能力,只是形式不一样。这些共性可以让两种事件模型之间的映射成为可能。
var EventUtil = { addHandler: function(element, type, handler) { // ... }, removeHandler: function(element, type, handler) { // ... }, getEvent: function(event) { // IE事件中以DOM0方式指定事件处理程序时,event对象是window的一个属性 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; } }, stopPropagation: function(event) { // 可能会中止事件冒泡,也可能既会中止事件冒泡也中止事件捕获 if(event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } } }; // 使用 let btn = document.querySelector('#myBtn'); btn.onclick = function(event) { event = EventUtil.getEvent(event); let target = EventUtil.getTarget(event); EventUtil.preventDefault(event); // 阻止事件的默认行为 EventUtil.stopPropagation(event); // 阻止事件冒泡 };
所发生事件的类型决定了事件对象中会保存什么信息。DOM3 Events定义的事件类型:
DOM3 Events在DOM2 Events基础上从新定义了事件,并增长了新的事件类型。全部主流浏览器都支持DOM2 Events和DOM3Events。
不必定跟用户操做有关。保留它们是为了向后兼容。主要有如下几种:
大多数HTML事件与window对象和表单控件有关。除了DOMActivate,其余在DOM2 Events中都被归为HTML Events。(DOMActivate是UI事件)
页面元素得到或失去焦点时触发。能够与document.hasFocus()和document.activeElement一块儿为开发者提供用户在页面中导航的信息。焦点事件有如下6种:
两个主要事件是focus和blur,它们最大的问题是不冒泡。
当焦点从页面中的一个元素A移到另外一个元素B上,会依次发生以下事件(测试,与书中不一致):
1)A:blur
2)A:focusout
3)B:focus
4)B:focusin
DOMFocusOut和DOMFocusIn未验证
鼠标是用户的主要定位设备。DOM3 Events定义了9种鼠标事件:
页面中全部元素都支持鼠标事件。除了mouseenter和mouseleave,其余鼠标事件都会冒泡,均可以被取消,这会影响浏览器的默认行为。因为事件之间存在关系,所以取消鼠标事件的默认行为也会影响其余事件。
双击鼠标主键会按以下顺序触发事件:
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
DOM3 Events中鼠标事件对应的类型是”MouseEvent“(单数形式)
鼠标事件还有一个名为滚轮事件的子类别。滚轮事件只有一个事件mousewheel,对应鼠标滚轮或带滚轮的相似设备上滚轮的交互。
鼠标事件event对象的一些属性:
客户端坐标
注:客户端坐标不考虑页面滚动
页面坐标
在页面上的位置。表示事件发生时鼠标光标在页面上的坐标,经过event对象的pageX和pageY属性获取。
反映的是光标到页面而非视口左边与上边的距离。
屏幕坐标
鼠标光标在屏幕上的坐标,经过event对象的screenX和screenY属性获取。
修饰键
有时要肯定用户想实现的操做,还要考虑键盘按键的状态。
键盘上的修饰键Shift、Ctrl、Alt和Meta(win的window键,mac的command键)常常用于修改鼠标事件的行为。
4个属性来表示这几个修饰键的状态:shiftKey、ctrlKey、altKey、metaKey。(被按下为true,不然为false)
如今浏览器支持全部4个修饰键,IE8及更早版本不支持metaKey属性。
相关元素
对mouseover和mouseout事件而言,还存在与事件相关的其余元素。
鼠标按键
对mousedown和mouseup事件来讲,event对象上会有一个button属性,表示按下或释放的是哪一个按键。DOM为button属性定义了3个值:0-主键;1-中键(一般是滚轮键);2-副键。
IE8及更早版本也提供了button属性,考虑了同时按多个键的状况。
额外事件信息
DOM2 Events规范在event对象上提供了detail属性,以给出关于事件的更多信息。对鼠标事件来讲,detail包含一个数值,表示在给定位置上发生了多少次单击(连续单击)。每次单击会加1。连续点击中断会重置为0。
IE还为每一个鼠标事件提供了如下额外信息:
滚轮mousewheel事件
在用户使用鼠标滚轮时触发,包括在垂直方向上任意滚动。会在任何元素上触发,并(在IE8中)冒泡到document和(全部现代浏览器中)window。
event对象包含鼠标事件的全部标准信息,此外还有一个名为wheelDelta的属性。
多数状况下只需知道滚轮滚动的方向,而这经过wheelDelta值的符号就能够知道。(向前滚动一次+120,向后滚动一次-120)
触摸屏设备
触摸屏一般不支持鼠标操做。
无障碍问题
若是Web应用或网站要考虑残障人士,特别是使用屏幕阅读器的用户,那么必须当心使用鼠标事件(除了回车键能够触发click事件,其余鼠标事件不能经过键盘触发)。建议不要使用click事件以外的其余鼠标事件向用户提示功能或触发代码执行。=> 会严格妨碍盲人或视障用户使用。
几条使用鼠标事件时应该遵循的无障碍建议:
更多网站无障碍的信息,能够参考WebAIM网站。
用户操做键盘时触发。很大程度上是基于原始的DOM0实现的。
DOM3 Events为键盘事件提供了一个首先在IE9中彻底实现的规范,其余浏览器也开始实现该规范,但仍存在不少遗留的实现。
包含3个事件:
全部元素都支持这些事件。但在文本框中输入内容时最容易看到。
输入事件只有一个:textInput。是对keypress事件的扩展,用于在文本显示给用户以前更方便地截获文本输入。会在文本被插入到文本框以前触发。
注:键盘事件支持与鼠标事件相同的修饰键。
键盘事件event对象的一些属性:
键码keyCode
keydown和keyup事件,event对象的keyCode属性会保存一个键码。
对于字母和数字键,keyCode的值与大写字母和数字的ASCII编码一致。与是否按了Shift键无关。
DOM和IE的event对象都支持keyCode属性
字符编码charCode
keypress事件,意味着按键会影响屏幕上显示的文本。对插入或移除字符的键,全部浏览器都会触发keypress事件,其余键则取决于浏览器。
event对象上的charCode属性,只有发生keypress事件时这个属性才会被设置值(此时与keyCode属性相等)。包含的是按键字符对应的ASCII编码。
IE8及更早版本和Opera使用keyCode传达字符的ASCII编码。要以跨浏览器方式获取字符编码,首先要检测charCode属性是否有值,若是没有再使用keyCode。
有了字母编码,就可使用String.fromCharCode()方法将其转换为实际的字符了。
DOM3的变化
DOM3 Events规范并未规定charCode属性,而是定义了key和char两个新属性。
key属性用于替代keyCode,且包含字符串。按下字符键时,key等于文本字符;按下非字符键时,key的值是键名(如”Shift“或”ArrowDown“)
char属性在按下字符键时与key相似,在按下非字符键时为null。(测试Chrome中keypress和keydown的event对象此属性都无)
IE支持key属性但不支持char属性。
Safari和Chrome支持keyIdentifier属性(测试Chrome无此属性)。对于字符键,keyIdentifier返回以”U+0000“形式表示Unicode值的字符串形式的字符编码。
因为缺少跨浏览器支持,不建议使用key、keyIdentifier和char。
DOM3 Events也支持一个名为location的属性,是一个数值,表示是在哪里按的键。可能的值为:0-默认键;1-左边;2-右边;3-数字键盘;4-移动设备(虚拟键盘);5-游戏手柄。Safari和Chrome支持一个等价的keyLocation属性(实现有问题)
没有获得普遍支持,不建议在跨浏览器开发时使用location属性。
给event对象增长了getModifierState()方法,接收一个参数,一个等于Shift、Control、Alt、AltGraph或Meta的字符串,表示要检测的修饰键。若是给定 的修饰键被按钮,则返回true。(也可直接使用event对象的shiftKey、ctrlKey、altKey或metaKey属性获取)
输入textInput事件
DOM3 Events规范新增,在字符被输入到可编辑区域时触发。
与keypress比对:1. keypress会在任何能够得到焦点的元素上触发,textInput只在可编辑区域上触发;2. textInput只在有新字符被插入时才会触发,而keypress对任何可能影响文本的键都会触发(包括退格键(Chrome里测试不会触发?))。3. 使用输入法(搜狗)时,在触发合成事件时不会触发keypress,在compositionend触发以前会先触发textInput事件。4. 使用键盘输入先触发keypress,再触发textInput。
该事件主要关注字符,event对象上有data属性,为被插入的字符(非字符编码);还有一个inputMethod的属性(Chrome中测试无此属性打印为undefined),表示向控件中输入文本的手段,能够辅助验证
设备上的键盘事件(非键盘)
任天堂Wii
DOM3 Events中新增,用于处理一般使用IME输入时的复杂输入序列。IME可让用户输入物理键盘上没有的字符,一般须要按下多个键才能输入一个字符,合成事件用于检测和控制这种输入。
合成事件有如下3种:
惟一增长的事件属性是data:
测试获得的触发顺序:
keydown -> ...start -> ...update -> ( (keyup) -> keydown -> ...update -> (keyup))(循环触发) -> ...update(此时data与...end事件中的data一致) -> textInput -> ...end -> keyup
DOM2的变化事件(Mutation Events),在DOM发生变化时提供通知。
(已废弃)
已经被Mutation Observers所取代(第14章)
HTML5中获得浏览器较好支持的一些事件(规范未涵盖)
contextmenu事件
单击鼠标右键(Ctrl+单击左键)。用于容许开发者取消默认的上下文菜单并提供自定义菜单。冒泡。
事件目标是触发操做的元素,这个事件在全部浏览器中均可以取消(event.preventDefault()或event.returnValue设置为false)。
一般经过onclick事件处理程序触发隐藏(自定义菜单)。
beforeunload事件
在window上触发。用于给开发者提供阻止页面被卸载的机会。在页面即将从浏览器中卸载时触发。
不能取消,不然就意味着能够把用户永久阻拦在一个页面上。
该事件会向用户显示一个确认框。用户能够点击取消或者确认离开页面。须要将event.returnValue设置为要在确认框中显示的字符串(对于IE和FF来讲)(测试FF显示的提示文字与returnValue属性值无关),并将其做为函数值返回(对于Safari和Chrome来讲)(测试Chrome无返回值也无影响)
DOMContentLoaded事件
会在DOM树构建完成后当即触发,而不用等待图片、JavaScript文件、CSS文件或其余资源加载完成。(能够在外部资源下载的同时指定事件处理程序,从而让用户可以更快地与页面交互)
比对load事件:要等待不少外部资源加载完成。
须要给document或window添加事件处理程序(实际的事件目标是document,会冒泡到window)。
一般用于添加事件处理程序或执行其余DOM操做。这个事件始终在load事件以前触发。
对于不支持DOMContentLoaded事件的浏览器,可使用超时为0的setTimeout()函数,经过其回调来设置事件处理程序。本质上是在当前JavaScript进程执行完毕后当即执行这个回调。(与DOMContentLoaded触发时机一致无绝对把握,最好是页面上的第一个超时代码)
readystatechange事件
IE首先定义。用于提供文档或元素加载状态的信息,但行为有时不稳定。
event.target或其余支持readystatechange事件的对象都有一个readyState属性,该属性可能为如下5个值:
并不是全部对象都会经历全部readyState阶段(Chrome测试document只经历了两个阶段:interactive和complete)
值为”interactive“的readyState阶段,时机相似于DOMContentLoaded。进入交互阶段,意味着DOM树已加载完成。(此时图片和其余外部资源不必定都加载完成了)。
与load事件共同使用时,这个事件的触发顺序不能保证。interactive和complete的顺序也不是固定的,为了抢到较早的时机,须要同时检测交互阶段和完成阶段(能够保证尽量接近使用DOMContentLoaded事件的效果)。
pageshow与pagehide事件
FF和Opera开发的一个名为往返缓存(bfcache,back-forward cache)的功能,旨在使用浏览器”前进“和”后退“按钮时加快页面之间的切换。不只存储页面数据,也存储DOM和JavaScript状态,其实是把整个页面都保存在内存里。
若是页面在缓存中,导航到这个页面时就不会触发load事件。
pagehide:在页面从浏览器中卸载后,在unload事件以前触发。事件目标是document,但事件处理程序必须添加到window上。event对象中的persisted属性为布尔值,表示页面在卸载后是否保存在往返缓存中。
注册了onunload事件处理程序的页面会自动排除在往返缓存以外(测试beforeunload也会影响),由于onunload的典型场景就是撤销onload事件发生时所作的事情,若是使用往返缓存,下一次页面显示时就不会触发onload事件,这可能致使页面没法使用。
hashchange事件
用于在URL散列值(#后面的部分)发生变化时通知开发者。
事件处理程序必须添加给window。event对象有两个新属性:oldURL和newURL,分别保存变化先后的URL,包含散列值的完整URL。若是想肯定当前的散列值,最好使用location对象。
智能手机和平板计算机=>交互的新方式
用于肯定用户使用设备的方式。
orientationchange事件
苹果,移动Safari浏览器。判断用户的设备是处于垂直模式仍是水平模式。window.orientation属性,有3种值:0-垂直模式,90-左转水平模式(Home键在右),-90-右转水平模式(Home键在左)。当属性值改变就会触发该事件。
全部iOS设备都支持该事件和该属性。(测试锁定竖屏=>不会改变)
被认为是window事件,也可给body元素添加onorientationchange属性来指定事件处理程序。
deviceorientation事件
DeviceOrientationEvent规范定义的事件。
若是能够获取设备的加速计信息,且数据发生了变化,就会在window上触发。只反应设备在空间中的朝向,与移动无关。
设备自己处于3D空间,x轴方向为从设备左侧到右侧,y轴方向为从设备底部到上部,z轴方向为从设备背面到正面。
event对象包含各个轴相对于设备静置时坐标值的变化,主要有5个属性:
测试iPhone8(iOS11.4.1)平放在桌面上也一直监听到变更(?),测试Android(一加三)平放在桌面上后不会变更
devicemotion事件
DeviceOrientationEvent规范定义的事件。
用于提示设备实际上在移动,而不只仅是改变了朝向。event对象包含的额外属性:
若是没法提供acceleration、accelerationIncludingGravity、rotationRate信息,则属性值为null。=> 使用以前必须先检测
测试iPhone8(iOS11.4.1)平放在桌面上也一直监听到变更,测试Android(一加三)平放在桌面上也一直监听到变更
只适用于触屏设备。
Webkit为Android定制了不少专有事件,成为了事实标准,并被归入W3C的Touch Events规范。
触摸事件
以下几种:
都会冒泡,均可以被取消。不属于DOM规范,浏览器以兼容DOM的方式实现它们。每一个触摸事件的event对象都提供了鼠标事件的公共属性,另外提供如下3个属性用于跟踪触点:
每一个Touch对象包含一些属性,可用于追踪屏幕上的触摸轨迹。(针对一个触点)touchend事件触发时touches集合中什么也没有,这是由于没有滚动的触点了。
当手指点触屏幕上的元素时,依次触发的事件(测试与书本不一致):
1)touchstart
2)touchend
3)mousemove
4)mousedown
5)mouseup
6)click
手势事件
iOS2.0中的Safari中增长。在两个手指触碰屏幕且相对距离或旋转角度变化时触发。有以下3种:
都会冒泡。
只有在两个手指同时接触事件接收者时(目标元素边界之内),这些事件才会触发。
触摸事件和手势事件存在必定的关系。
每一个手势事件的event对象都包含全部标准的鼠标事件属性,新增了两个属性是rotation和scale。
rotation:表示手指变化旋转的度数,负值表示逆时针旋转,正值表示顺时针旋转(从0开始);
scale:表示两指之间距离变化(对捏)的程度,开始时为1,而后随着距离增大或缩小相应地增大或缩小。
触摸事件也会返回rotation和scale属性,但只在两个手指触碰屏幕时才会变化。
参考书本
在JavaScript中,页面中事件处理程序的数量与页面总体性能直接相关。
首先,每一个函数都是对象,都占用内存空间;其次,为指定事件处理程序所需访问DOM的次数会先期形成整个页面交互的延迟。
改善页面性能?
”过多事件处理程序“的解决方案是使用事件委托。
利用事件冒泡,能够只使用一个事件处理程序来管理一种类型的事件。只要给全部元素(须要处理某种事件的元素)共同的祖先节点添加一个事件处理程序,就能够解决问题(根据target判断进行不一样的处理)。=> 只访问了一个DOM元素和添加了一个事件处理程序。 => 占用内存更少,全部使用按钮的事件(大多数鼠标事件和键盘事件)都适用于这个解决方案。
只要可行,就应该考虑只给document添加一个事件处理程序,经过它处理页面中全部某种类型的事件。优势以下:
最适合使用事件委托的事件包括:click、mousedown、mouseup、keydown和keypress。
把事件处理程序指定给元素后,在浏览器代码和负责页面交互的JavaScript代码之间就创建了联系。这种联系创建得越多,页面性能就越差。除了使用事件委托减小这种联系外,还应及时删除不用的事件处理程序。
不少Web应用性能不佳都是因为无用的事件处理程序长驻内存致使的。缘由以下:
删除带有事件处理程序的元素。如使用方法removeChild()或replaceChild()删除节点,或使用innerHTML总体替换页面的某一部分。=> 被删除的元素上如有事件处理程序,就不会被垃圾收集程序正常清理。(特别是IE8及更早版本,元素的引用和事件处理程序的引用)
若是知道某个元素会被删除,那么最好在删除它以前手工删除它的事件处理程序(或者不直接给它添加事件处理程序,使用事件委托)。=>确保内存被回收,元素也能够安全地从DOM中删掉。
注意:在事件处理程序中删除元素会阻止事件冒泡。只有事件目标仍然存在于文档中时,事件才会冒泡。
页面卸载致使内存中残留引用。事件处理程序没有被清理,会残留在内存中。
最好在onunload事件处理程序中趁页面还没有卸载先删除全部事件处理程序。=> 使用事件委托的优点:事件处理程序不多。
一般事件都是由用户交互或浏览器功能触发。
能够经过JavaScript在任什么时候候触发任意事件 => 在测试Web应用时特别有用
DOM3规范指明了模拟特定类型事件的方式。
步骤:
使用document.createEvent()方法建立一个event对象。
createEvent()方法接收一个参数,一个表示要建立事件类型的字符串。DOM2是英文复数形式,DOM3中是英文单数形式。可用值为如下之一:
使用事件相关的信息来初始化
每种类型的event对象都有特定的方法,取决于调用createEvent()时传入的参数
触发事件
事件目标调用dispatchEvent()方法。该方法存在于全部支持事件的DOM节点上。
接收一个参数,即要触发事件的event对象
不一样事件类型的模拟:
鼠标事件
全部鼠标事件均可以在DOM合规的浏览器中模拟出来
键盘事件
DOM3 Events中废弃了keypress事件,所以只能经过上述方式模拟keydown和keyup事件。
在使用document.createEvent("KeyboardEvent")
以前,最好检测一下浏览器对DOM3键盘事件的支持状况document.implementation.hasFeature("KeyboardEvents", "3.0")
。
测试Chrome,调用initKeyboardEvent()方法传入的key和modifier参数与在事件处理程序中打印出来的属性不一致,可使用new KeyboardEvent()
(参数与在事件处理程序中打印出的一致),另,两种模拟都不会使文本框中有内容
FF限定:
测试:ff(88.0)显示不支持 Uncaught DOMException: Operation is not supported
其余不支持键盘事件的浏览器:
必须使用通用事件而不是用户界面事件,由于用户界面事件不容许直接给event对象添加属性
其余事件
HTML事件:
测试:模拟focus,能监听到事件,可是没有光标
自定义DOM事件
DOM3新增自定义事件类型。不触发原生DOM事件。
在IE8及更早版本中模拟事件。
步骤:
IE支持的全部事件均可以经过相同的方式来模拟。
最多见的事件是在DOM3 Events规范或HTML5中定义的。
须要考虑内存与性能问题:
限制页面中事件处理程序数量。=> 避免占用过多内存致使页面响应慢,清理起来更方便