Javascript高级程序设计(笔记)–13章

事件

使用侦听器(或处理程序)来预订事件, 以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型

DOM2级事件

1.ie8及以前除外所有浏览器均已支持

2.dom2事件并没有包含所有事件类型+Bom事件===》dom3级事件事件增强

事件流

1.事件流描述的是从页面中接收事件的顺序

2.IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事件捕获流

事件冒泡

定义: 即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点 接收,然后逐级向上传播到较为不具体的节点(文档)–由内到外

浏览器支持:所有现代浏览器都支持事件冒泡

浏览器差异: IE5.5 及更早版本中的事件冒泡 会跳过元素,从body直接跳到document

IE9、Firefox、Chrome 和 Safari 则将事件一直冒泡到 window 对象

事件捕获

定义: 事件捕获的思想是不太具体的节点应该更早接收到事件而最具体的节点应该最后接收到事件–由外到内

DOM事件流

“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段

注意:1.DOM2级事件要求事件捕获阶段从document->body ,下一阶段为“处于目标”阶段,当事件发生后再处理事件中被看成是冒泡阶段的一部分,然后冒泡阶段发生

2.但 IE9、Safari、Chrome、Firefox 和 Opera 9.5 及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上面操作事件

事件处理程序

事件:点击事件,load,mouse事件,用户或浏览器自身执行的某种动作

事件处理程序:响应某个事件的函数–名字以 “on” 开头(onclick,onload)

关联:为事件指定事件处理 程序

事件处理程序(事件侦听器)

事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码

event:局部变量 event事件对象

this:值等于事件目标元素

其作用域的扩展

function(){
  with(document){
    with(this){
     //元素属性值
  }
}

<form method="post">
<input type="text" name="username" value="">
<input type="button" value="Echo Username" onclick="alert(username.value)">
</form> //单击按钮显示userName

with:的使用请参考——https://www.jb51.net/article/12326.htm

假设 showMessage() 函数是在按钮下方、页面的最底部定义的。如果用户在页面解析 showMessage()函数之前就单击了按钮,就会引发错误。为此,很多 HTML 事件处理程序都会被封装在一个 try-catch 块中,以便错误不会浮出水面

<input type="button" value="Click Me" onclick="try{showMessage();}catch(ex){}">

DOM0 级事件处理程序

要使用 JavaScript 指定事件处理程序

var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert(this.id); //"myBtn"
}

注意

  • 这些代码运行时才会指定事件处理程序–所以如果按钮先显示,有可能在一定时间内点击无响应
  • DOM0 级方法指定的事件处理程序被认为是元素的方法,这时候的事件处理程序是在 元素的作用域中运行(程序中的 this 引用当前元素
  • 以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理

DOM2 级事件处理程序

addEventListener()和 removeEventListener()

注意

  • 第三个参数,Boolean:true(处于捕获阶段触发),false(默认,处于冒泡阶段触发)
  • 可以添加多个事件处理程序(两个click事件都可以执行)
  • 只能使用 removeEventListener() 来移除,且参数要相同
  • 兼容:ie9+

推荐使用冒泡阶段,捕获阶段只推荐在需要事件到达目标之前截获它的时候使用

IE事件处理程序

attachEvent() 和 detachEvent()

注意

  • ie8以下使用
  • 由于 IE8 及更早版本只支持事件冒泡所以事件只会被添加到冒泡阶段
  • 与上不同的是第一个参数为:onClick(上为click)
  • 作用域与上不同:全局作用域中运行(this===window)
  • 可以添加多个事件处理程序(两个click事件都可以执行但执行顺序相反)
  • 兼容ie&opera

事件对象

:在触发 DOM 上的某个事件时,会产生一个事件对象 even-包含着所有与事件有关的
信息

包括的信息有

  • 导致事件的元素
  • 事件的类型以及其他与特定事件相关的信息(1.鼠标事件中:鼠标位置的信息..2.键盘事件中:包含与按下的键有关的信息)
  • 只有在处理程序执行时event对象才存在,执行完成即被销毁

DOM中的事件对象

var btn = document.var btn = document.getElementB
属性/方法 类型 读写 说明
bubbles Boolean 是否冒泡
cancelable B 是否可以取消事件的默认行为
currentTarget Element 其事件处理程序当前正在处理事件的那个元素
target 事件的目标
eventPhase Integer 当前事件所处阶段:1捕获阶段2处于目标上3冒泡阶段
defaultPrevented B 为 true 表 示 已 经 调 用 了 preventDefault()
preventDefault() Function 取消事件的默认行为。如果 cancelable 是
true则
可以调用此方法
stopImmediatePropagation() F 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调
stopPropagation() F 取消事件的进一步捕获或冒泡。如果 bubbles为 true则可以调用此方法
trusted B 为 true 表示事件是浏览器生成的。为 false 表事 件 是 由 开 发 人 员 通 过 JavaScript创 建 的(DOM3级事件中新增)
type String 被触发的事件的类型
view AbstractView 与事件关联的抽象视图。等同于发生事件的window 对象

注意

事件处理程序中的this,currentTarget,target的关系

  • 如果事件直接绑定到目标元素则三者值相同
  • 如果事件绑定到父节点(如document.body)值各不相同:this == event.currentTarget == document.body; event.target === 当前点击元素

IE中的事件对象

btn.onclick = function(){
var event = window.event;
alert(event.type); //"click"
} 

在IE中Dom0级事件绑定中event 对象作为 window 对象的一个属性存在

属性/方法 类型 读写 说明
cancelBubble Boolean 默认为false,设置为true取消事件冒泡与(DOM中的stopPropagation方法相同)
returnValue B 默认值为 true ,但将其设置为 false 就可以取消事件的默认行为(与DOM中的 preventDefault()方法相同)
srcElement Element 事件目标 (与Dom中的target相同)
type String 事件类型

事件类型(DOM3)

  • UI事件:用户与页面的元素交互时触发
  • 焦点事件:当元素获得或失去焦点时触发
  • 鼠标事件:当用户通过鼠标在页面上执行操作时触发
  • 滚轮事件:当使用鼠标滚轮(或类似设备)时触发
  • 文本时间:当在文档中输入文本时触发
  • 键盘事件:用户通过键盘在页面上执行操作时触发
  • 合成时间:当为 IME(Input Method Editor,输入法编辑器)输入字符时触发
  • 变动(mutation)事件:当底层 DOM 结构发生变化时触发
  • 变动名称事件:当元素或属性名变动时触发。此类事件已经被废弃,没有浏览器实现他们
  • 还有一些非通用的由浏览器定制的专有事件

UI事件

ui事件名称 定义 兼容 详解
DOMActivate 元素被用户操作(通过鼠标或键盘)激活 DOM3废弃,ff与Chrome支持
load 1.当页面完全加载(img,js,css等外部资源都加载完成)后在 window 上面触发
2.当所有框架都加载完毕时在框架集上面触发
3.当图像加载完毕时在 元素上面触发 (图像不在DOM文档中指定了src也触发)
4.当嵌入的内容加载完毕时在<a rel="noreferrer noopener" aria-label="(在新窗口打开)” href=”https://www.w3school.com.cn/tags/tag_object.asp” target=”_blank”>元素上面
触发
5.非标准的实现在IE9+中中也支持load(必须在dom文档中才会下载文件
EventUtils.addHandler(
window,load,function(event){
alert(event);
//event 对象中不包
含有关这个事件的任何附加信息,
//但是在兼容DOM的浏览器中event.target返回document
})

2.image中load事件,如果使用未绑定到DOM元素上的img元素做load监听,event在IE8及以下不存在
unload 1.当页面完全卸载后在 window 上面触发,
2.当所有框架都卸载后在框架集上面触发
3.当嵌入的内容卸载完毕后在元素上面触发
只要用户从一个页面切
换到另一个页面,就会发生 unload(此特性来清除引用)
EventUtil.addHandler(window, “unload”, function(event){
alert(event);//ie9+兼容dom的浏览器event.target === document
//ie8 event.srcElement
})
注意:卸载之后才触发,那么在页面加载后存在的那些对象,此时就不存在了DOM节点或元素样式修改报错
abort 在用户停止下载过程时,如果嵌入的内容没有加载完,则在元素上面触发
error 1.当发生 JavaScript 错误时在 window 上面触
2.当无法加载图像时在 元素上面触发
3.当无法加载嵌入内容时在元素上面触发

select 当用户选择文本框(input/textarea)中的一或多个字符时触发
resize 当窗口或框架的大小变化时在 window 或框架(iframe)上面触发 1.IE、Safari、Chrome 和 Opera 会在浏览窗口变化一像素时触发,随后随变化重复触发
2.最大化最小化窗口也会触发
scroll 当用户滚动带滚动条的元素中的内容时,在该元素上面触发 1.window对象上发生,但实际表示是页面上相应元素的变化
2.混杂模式下元素的scrollLeft与scrollTop监控变化,标准模式下除了safari都使用html反应变化
EventUtil.addHandler(window, “”scroll”, function(event){
if(document.compatMode == “CSS1Compat”){//标准模式
alert(document.documentElement.scrollTop);
//html元素变化
}
else{
alert(document.body.scrollTop)//body元素变化
}

注意:

  • 以上事件除了DomActive事件为ui事件外
  • 其他的均属于DOM2事件中的HTML事件–如何检测当前浏览器是否支持dom2
  • 一般来说,在 window 上面发生的任何事件都可以在元素中通过相应的特性来指定,这只是为了保证向后兼容,建议使用js的方式
var isSupported = document.implementation.hasFeature("HTMLEvents", "2.0");//(前提此浏览器根据标准DOM2事件来实现这些事件则返回true)
var isSupported = document.implementation.hasFeature("UIEvent", "3.0");//同上

焦点事件

焦点事件名称 定义 兼容 详解
blur 在元素失去焦点时触发 所有浏览器
DOMFocusIn 在元素获得焦点时触发(与HTML 事件 focus 等价),但他冒泡 只有Opera支持事件,DOM3废弃使用focusin
DOMFocusOut 在元素失去焦点时触发 与DOMfocusIn类似,DOM3使用focusout
focus 在元素获得焦点时触发。这个事件不会冒泡 所有浏览器
focusin 在元素获得焦点时触发(与Html事件focus等价),支持冒泡 IE5.5+、Safari 5.1+、Opera 11.5和Chrome
focusout 在元素失去焦点时触发(与Html事件blur等价),支持冒泡 IE5.5+、Safari 5.1+、Opera 11.5和Chrome

注意

  • 保证浏览器是否支持事件
var isSupported = document.implementation.hasFeature("FocusEvent", "3.0");//支持DOM3事件
  • focus与blur不支持冒泡,但在捕获阶段可以侦听

鼠标与滚轮事件

事件名称 定义 兼容 详解
click 在用户单击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发
dbclick 在用户双击主鼠标按钮(一般是左边的按钮)时触发 DOM3事件
mousedown 在用户按下了任意鼠标按钮时触发。不能通过键盘触发这个事件
mouseenter 在鼠标光标从元素外部首次移动到元素范围之内时触发,这不冒泡 而且在光标移动到后代元素上不会触发(即在子元素后代元素上也算在当前范围内) IE、Firefox 9+和 Opera 支持这个事件
DOM3
mouseleave 在位于元素上方的鼠标光标移动到元素范围之外时触发。这个事件不冒泡而且在光标移动到后代元素上不会触发(即在子元素后代元素上也算在当前范围内) DOM3
同上
mousemove 当鼠标指针在元素内部移动时重复地触发
mouseout 在鼠标指针位于一个元素上方,然后用户将其移入另一个元素(另一个元素可以是父/子元素)时触发
mouseover 在鼠标指针位于一个元素外部,然后用户将其首次移入另一个元素边内时触发
mouseup 在用户释放鼠标按钮时触发。不能通过键盘触发这个事件
mousewheel 这个事件可以在任何元素上面触发,会冒泡到 document (IE8)或 window (IE9、Opera、Chrome 及safary)对象上
DOMMouseScroll 于mouseWheel类似event.detail返回滚轮以3位倍数的值 FireFox 特有

注意

  • 除了 mouseenter 和 mouseleave ,所有鼠标事件都会冒泡也可以被取消,取消鼠标事件将会影响浏览器的默认行为
  • 取消鼠标事件的默认行为还会影响其他事件,因为鼠标事件与其 他事件是密不可分的关系
  • 相继触发 mousedown 和 mouseup 事件,才会触发click事件,其中一个被取消click事件将不会触发
  • 只有触发两次click才会触发一次dbclick,间接取消mousedown/mouseup也将无法触发dbclick
  • 在触摸设备中
    • 不支持dbclick事件,双击放大此行为不可更改
    • 轻击可单击元素会触发mouseMove事件,如果会发生内容变化其他事件则不再发生如果屏幕内容未变,依次发生mousedown,mouseup,click,(可单击元素:有默认行为的如(a链接),或者指定了onclick事件的元素)
    • mousemove事件也会触发mouseover与mouseout事件
    • 两根手指在屏幕上滚动页面时会触发mousewheel与scroll事件
  • 无障碍性问题
    • 对于盲人或者屏幕阅读器使用者
    • 屏幕阅读器 无法触发mousedown事件和mouseover
    • 如果考虑无障碍别使用dbclick,键盘无法触发