JS页面事件(非常详细)
所有页面事件都明确的处理整个页面的函数和状态。主要包括页面的加载和卸载,即用户访问页面和离开关闭页面的事件类型。
页面初始化
load 事件类型在页面完全加载完毕的时候触发。该事件包含所有的图形图像、外部文件(如 CSS、JS 文件等)的加载,也就是说,在页面所有内容全部加载之前,任何 DOM 操作都不会发生。为 window 对象绑定 load 事件类型的方法有两种。
1) 直接为 window 对象注册页面初始化事件处理函数。
window.onload = f;
function f() {
alert("页面加载完毕");
}
2) 在页面 <body> 标签中定义 onload 事件处理属性。
<body onload="f()">
<script>
function f() {
alert("页面加载完毕");
}
</script>
示例1
如果同时使用上面两种方法定义页面初始化事件类型,它们并不会发生冲突,也不会发生两次触发事件。
<body onload="f()">
<script>
window.onload = f;
function f() {
alert("页面加载完毕");
}
</script>
</body>
原来 JavaScript 解释器在编译时,如果发现同时使用两种方法定义 load 事件类型,会使用 window 对象注册的事件处理函数覆盖掉 body 元素定义的页面初始化事件属性。
示例2
在下面示例中,函数 f2() 被调用,而函数 f1() 就被覆盖掉。
<body onload="f1()">
<script>
window.onload = f2;
function f1 () {
alert('<body onload="f1()">');
}
function f2 () {
alert('window.onload = f2;');
}
</script>
</body>
在实际开发中,load 事件类型经常需要调用附带参数的函数,但是 load 事件类型不能够直接调用函数,要解决这个问题,有以下两种方法。
1) 在 body 元素中通过事件属性的形式回调函数。
<body onload="f('Hi')">
<script>
function f (a) {
alert(a);
}
</script>
</body>
2) 通过函数嵌套或闭包函数来实现。
window.onload = function () { //事件处理函数
f("Hi"); //调用函数
}
functioin f(a) { //被处理函数
alert(a);
}
也可以采用闭包函数形式,这样在注册事件时,虽然调用的是函数,但是其返回值依然是一个函数,不会引发语法错误。
window.onload = f("Hi");
function f(a) {
return function () {
alert(a);
}
}
通过这种方法,可以实现在 load 事件类型上绑定更多的响应回调函数。
window.onload = function () {
f1(); //绑定响应函数1
f2(); //绑定响应函数2
}
function f1() {
alert("f1()");
}
function f2() {
alert("f2()");
}
但是,如果分别绑定 load 事件处理函数,则会相互覆盖,最终只能够有一个绑定响应函数被调用。
window.onload = f1();
function f1(){
alert("f1()");
}
function f2() {
alert("f2()");
}
也可以通过事件注册的方式来实现。
if (window.addEventListener) { //兼容DOM标准
window.addEventListener ("load", f1, false); //为load添加事件处理函数
window.addEventListener ("load", f2,false); //为load添加事件处理函数
} else { //兼容IE事件模型
window.attachEvent ("onload", f1);
window.attachEvent ("onload", f2);
}
结构初始化
在传统事件模型中,load 是页面中最早被触发的事件。不过当使用 load 事件来初始化页面时可能会存在一个问题,就是当页面中包含很大的文件时,load 事件需要等到所有图像全部载入完成之后才会被触发。也许用户希望某些脚本能够在页面结构加载完毕之后就能够被执行。要怎么办呢?
这时可以考虑使用 DOMContentLoaded 事件类型。作为 DOM 标准事件,它是在 DOM 文档结构加载完毕的时候触发的,因此要比 load 事件类型先被触发。目前,Mozilla 和 Opera 新版本已经支持了该事件。而 IE 和 Safari 浏览器还不支持。
示例1
如果在标准 DOM 中,可以这样设计。
<script>
window.onload = f1;
if (document.addEventListener) {
document.addEventListener ("DOMContentLoaded", f, false);
}
function f () { alert("我要提前执行了"); }
function f1 () { alert("页面初始化完毕"); }
</script>
<img src="Winter.jpg">
这样,在图片加载之前会弹出“我要提前执行了”的提示信息,而当图片加载完毕之后会弹出“页面初始化完毕”。这说明在页面 HTML 结构加载完毕之后触发 DOMContentLoaded 事件类型,也就是说,在文档标签加载完毕时触发该事件并调用函数 f(),然后,当文档所有内容加载完毕(包括图片下载完毕)时才触发 load 事件类型,并调用函数 f1()。
示例2
由于 IE 事件模型不支持 DOMContentLoaded 事件类型,为了实现兼容处理,需要运用一点小技巧,即在文档中写入一个新的 script 元素,但是该元素会延迟到文件最后加载。然后,使用 Script 对象的 onreadystatechange 方法进行类似的 readyState 检查后及时调用载入事件。
if (window.ActiveXObject) { //兼容IE事件模型
document.write ("<script id=ie_onload defer src=javascript:void(0)><\/script"); //写入脚本标签
document.getElementById("ie_load").onreadystatechange = function () {
//判断脚本标签的状态
if (this.readyState == "complete") { //如果状态为完成,则说明文档结构加载已完毕
this.onreadystatechange = null; //清空当前反腐
f(); //调用预先执行的回调函数
}
}
}
写入的 <script> 标签中包含了 defer属性,defer 表示“延期”的意思,使用 defer 属性可以让脚本在整个页面装载完成之后在解析,而非边加载边解析。这对于只包含事件触发的脚本来说,可以提高整个页面的加载速度。与 src 属性联合使用,还可以使这些脚本在后台被下载,而前台的内容正常显示给用户。目前只有 IE 事件模型支持该属性。当定义了 defer 属性后,<script> 标签中就不应包含 document.write 命令,因为 document.write 将产生直接输出的效果,而且不包含任何立即执行脚本要使用的全局变量或者函数。
<script> 标签在文档结构加载完毕之后才加载,于是,只要判断它的状态就可以确定当前文档结构是否已经加载完毕并触发响应的事件。
示例3
针对 Safari 浏览器,可以使用 setInterval() 函数周期性的检查 document 对象的 readyState 属性,随时监控文档是否加载完毕,如果完成则调用回调函数。
if (/WebKit/i.test(navigator.userAgent)) { //兼容Safari浏览器
var _timer = setInterval (function () { //定义时间监测器
if (/loaded|complete/.test(document.readyState) { //如果当前状态显示完成
clearInterval(_timer); //清空时间监测器
f(); //调用预先执行的回调函数
}
}, 10);
}
把上面 3 段条件合并在一起即可实现兼容不同浏览器的 DomContentLoaded 事件处理函数。
页面卸载
unload 表示卸载的意思,这个事件在从当前浏览器窗口内移动文档的位置时触发,也就是说,通过超链接、前进或后退按钮等方式词能够一个页面跳转到其他页面,或者关闭浏览器窗口时触发。
示例
下面函数的提示信息将在卸载页面时发生,即在离开页面或关闭窗口前执行。
window.onunload = f;
function f() {
alert("888");
}
在 unload 事件类型中无法有效阻止默认行为,因为该事件结束后,页面将不复存在。由于在窗口关闭或离开页面之前只有很短的时间来执行事件处理函数,所以不建议使用该事件类型。使用该事件类型的最佳方式是取消该页面的对象引用。
beforeunload 事件类型与 unload 事件类型的功能相近,不过它更人性化,如果 beforeunload 事件处理函数返回字符串信息,那么该字符串会显示在一个确认对话框中,询问用户是否离开当前页面。例如,运行下面的示例,当刷新或关闭页面时会弹出以下提示信息。
window.beforeunload = function (e) {
return "您的数据还没有保存!";
}
演示结构如下: