DOM规范没有涵盖所有浏览器支持的所有事件
而许多浏览器出于满足用户需求,或解决特殊问题的目的,实现了一些自定义事件
HTML5列出了浏览器应该支持的所有事件,这里只讨论得到浏览器完善支持的事件(并非全部)
contextmenu事件
windows95 在PC中引入了上下文菜单的概念,即通过鼠标右键可以调出上下文菜单
在该概念提出后不久,该概念也被引入了web 领域
在web中实现该概念,开发人员面临的主要问题是:1.如何确定上下文菜单以何种方式打开(windows中鼠标右键,Mac中 ctrl + 单击) 2.如何屏蔽默认的上下文菜单的行为
为解决以上问题,出现了 contextmenu 这一事件,该事件触发时表示正在访问上下文菜单
通过这一事件,开发人员可以方便地提供自定义菜单
由于该事件是冒泡的,所以我们只需要为 document 提供事件处理程序,就可以将默认的菜单行为替代为我们自定义的菜单
需要注意的是该事件属于鼠标事件,所以在其事件对象上会提供光标位置有关的属性
通过这一属性我们就可以将我们的自定义菜单放到用户触发该事件时的位置,也就像我们平常使用的时候那样菜单出现在我们光标的位置
不过在使用时我们还需要阻止浏览器的默认菜单行为
在兼容DOM的浏览器中,我们可以使用 event.preventDefalut() 方法来取消浏览器的默认菜单行为
在不兼容DOM的浏览器中(如 IE低版本) 则需要将 event.returnValue 设置为false 来阻止默认行为
如下代码所示:
<ul style = "position:absolute;visibility:hidden;background-color:sliver" id="menu">
<li><a href="www.baidu.com">百度</a><li>
<li><a href="www.google.com">谷歌</a><li>
<ul>
上方代码在文档中创建了一个隐藏的菜单,该菜单由两个网址连接组成
这样我们就准备好了自定义菜单,下面我们则需要把浏览器默认的上下文菜单替换为我们的自定义菜单
window.onload = function(event){//当文档加载完成我们就需要替换掉默认的菜单
var menu = document.getElementById("menu"); document.addEventLinsener("contentmenu",function(events){
events.preventDefault();//阻止默认行为
menu.style.left = events.clientX + "px";
menu.sytle.top = event.clientY + "px";
menu.style.visibility = "visible"
},false); document.onlick = function(){
menu.style.visibility = "hidden";
}// 点击页面隐藏菜单
}
需要注意的是,我上方的示例没有做兼容处理,如需要跨浏览器使用则需要对事件绑定,以及事件对象进行兼容
可以参考 这篇文章,而支持该事件的浏览器有: IE Chrome Firefox Safari Opera 11+
beforeunload事件
beforeunload事件用于让开发人员能够在浏览器卸载页面之前,阻止这一行为
这一事件主要用于,弹出一个询问是否离开当前页面的弹窗,通过这一事件将控制权交给用户,防止因用户的误操作带来的不便
那么如何在浏览器中实现呢?
如下方代码所示:
window.addEventListener("beforeunload",function(event){
event.preventDefault();
event.returnValue = '';//chrome浏览器需要设置
},false);
处于安全性的考虑,现代的主流浏览器并不支持由我们来提供用户的提示信息
也就是我们没有必要设置 returnValue,但是chrome 浏览器需要设置以下该值(什么值都行只要不是undefined)才能正常工作
DOMContentLoaded事件
我们知道,window的load事件会在页面中的所有内容加载完毕后触发
但是往往我们在DOM结构建立完成的时候就需要对页面内容进行操作了,如果加载css等资源的时间过长,那么用户如果在这加载期间进行操作,就会给人没有响应的感受,脾气不好的用户很可能就会关掉网页,这当然不是我们想要看到的
对于这样的一种需求,DOMContetLoaded 事件应运而生
该事件在当前文档形成完整的DOM树之后就会触发
通过该事件我们可以让用户更早地和页面进行交互
要处理这一事件我们可以对 Document、window 绑定事件处理程序
虽然该事件会冒泡到window,但是该事件的目标是document
而这一事件的 event 事件对象并不会提供额外的信息
而对于不支持该事件的浏览器我们可以使用以下代码来代替:
setTimeout(function(){
//在此添加事件处理程序
},0);
需要注意的是,这样的写法并不一定代表这样添加的事件处理程序一定会早于load事件触发
readystatechange事件
IE为DOM中的某些部分提供,readystatechange 事件
该事件用于提供文档或元素加载状态的有关信息
该事件的事件对象有一个readyState 属性
该属性的值为下面五个值中的一个:
- uninitialized:尚未初始化
- loading:正在加载数据
- loaded:对象加载数据完成
- interactive:可以操作,尚未完全加载
- complete:对象已经加载完毕
需要注意的是并非所有的对象都会经历以上的五个状态,通常情况下该事件触发次数会少于四次
对于document而言,值为“interactive”的阶段与 DOMContentLoaded 事件的阶段大致相同
该事件与DOMContentLoaded 事件最大的区别在于,无法判断该事件与 load 事件的先后顺序
也就是这一事件并不一定会早于load事件触发
所以如果希望页面尽早开始交互可以使用以下代码:
document.attachEvent("onreadystatechange",function(event){
if(document.readyState =="intertactive" || document.readyState =="complete"){
document.detachEvent("onreadystatechange",arguments.callee,false);//解除事件处理程序
//需要进行的页面操作
}
},false)
支持readystatechange事件的浏览器有 IE、firefox、Opera,上方的例子以IE为例
需要注意的是:上方的代码可以近似地模拟DOMContentLoaded事件,但是其本质上仍是不同的,在不同的页面中load事件与readystatechange事件并不能保证以相同的顺序触发
pageshow与pagehide事件
在Firefox与Opera浏览器中有一个特性,叫“往返缓存”,用于当用户使用“前进”、“后退”按钮时加快页面的转换速度
本质上该特性相当于将当前整个页面存在内存中,所以当我们在上述浏览器使用前进、后退时并不会触发load事件
为此Firefox提供了一些新的事件
其中 pageshow 事件会在页面显示时触发,无论页面是否来自“往返缓存”
该事件会在load事件之后触发
虽然该事件的目标是document 但是必须将该事件的事件处理程序添加到 window 才能正常生效
该事件的事件对象有一个 persisted 的布尔值属性,如果页面来自 “往返缓存”则为 true 否则为 false
与pageshow 对应的是pagehide,该事件会在页面卸载时触发(早于unload事件)
对于这两个事件,只有IE9以下和Safari5以下的浏览器不支持
hashchange事件
hashchange事件应该说是这些事件中用途最广的了
前些时候,当前后分离是主流的web应用的开发模式的时候,hashchange事件可以说是功不可没
url中的hash值可以用来在不同页面之间传递信息,也就是前端路由的一种实现方式
现如今更多的时候 hashchange事件用于单页应用
我们知道单页应用只有一个HTML页面,通过这一个页面来实现许多复杂的功能
通过 hashchange 事件我们可以将单页应和多页应用的表现一致化
话说回来,该事件会在页面的 url 中的 # 后面的部分(hash值)发生变化时触发
该事件的event 对象包含两个额外的属性:
- oldURL:变化前的url
- newURL:变化后的url
虽然大多数浏览器实现了 hashchange事件
但是其中只有一部分支持,上面的额外属性,所以最好使用loaction 对象来获取当前的 url的参数列表(location.hash)