页面生命周期

DOMContentLoaded

浏览器已经完全加载了HTML,DOM树已经构建完毕,但是像是 和样式表等外部资源可能并没有下载完毕。

1
2
3
document.addEventListener("DOMContentLoaded", function() {
console.log('DOMContentLoaded')
})

DOMContentLoaded 和脚本

当浏览器在解析HTML页面时遇到了 标签,将无法继续构建DOM树(译注:UI渲染线程与JS引擎是互斥的,当JS引擎执行时UI线程会被挂起),必须立即执行脚本。所以 DOMContentLoaded 有可能在所有脚本执行完毕后触发。

外部脚本(带src的)的加载和解析也会暂停DOM树构建,所以 DOMContentLoaded 也会等待外部脚本。
不过有两个例外是带async和defer的外部脚本,他们告诉浏览器继续解析而不需要等待脚本的执行,所以用户可以在脚本加载完成前可以看到页面,有较好的用户体验。
async和defer属性仅仅对外部脚本起作用,并且他们在src不存在时会被自动忽略。
它们都告诉浏览器继续处理页面上的内容,而在后台加载脚本,然后在脚本加载完毕后再执行。所以脚本不会阻塞DOM树的构建和页面的渲染。
其实这里是不对的,带有async和defer的脚本的下载是和HTML的下载与解析是异步的,但是js的执行一定是和UI线程是互斥的,像下面这张图所示,async在下载完毕后的执行会阻塞HTML的解析

两处不同

async defer
带有async的脚本是优先执行先加载完的脚本,他们在页面中的顺序并不影响他们执行的顺序。 带有defer的脚本按照他们在页面中出现的顺序依次执行。
带有async的脚本也许会在页面没有完全下载完之前就加载,这种情况会在脚本很小或本缓存,并且页面很大的情况下发生。 带有defer的脚本会在页面加载和解析完毕后执行,刚好在 DOMContentLoaded之前执行。

浏览器的自动补全

Firefox, Chrome和Opera会在DOMContentLoaded执行时自动补全表单。
例如,如果页面有登录的界面,浏览器记住了该页面的用户名和密码,那么在 DOMContentLoaded运行的时候浏览器会试图自动补全表单(如果用户设置允许)。
所以如果DOMContentLoaded被一个需要长时间执行的脚本阻塞,那么自动补全也会等待。你也许见过某些网站(如果你的浏览器开启了自动补全)—— 浏览器并不会立刻补全登录项,而是等到整个页面加载完毕后才填充。这就是因为在等待DOMContentLoaded事件。
使用带async和defer的脚本的一个好处就是,他们不会阻塞DOMContentLoaded和浏览器自动补全。(译注:其实执行还是会阻塞的)

load

附加资源已经加载完毕,可以在此事件触发时获得图像的大小(如果没有被在HTML/CSS中指定)

1
2
3
window.onload = function() {
console.log('onload')
}

readyState

document.readyState

  1. loading 加载 - document仍在加载。
  2. interactive 互动 - 文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
  3. complete - 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。
1
2
3
4
5
6
7
8
9
function work() {
console.log('work')
}
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', work);
} else {
work();
}

readystatechange

每当文档的加载状态改变的时候就有一个readystatechange事件被触发,所以我们可以打印所有的状态。

1
document.addEventListener('readystatechange', () => console.log(document.readyState))

unload

beforeunload

即将离开页面或者关闭窗口时
有些浏览器像Chrome和火狐会忽略返回的字符串取而代之显示浏览器自身的文本,这是为了安全考虑,来保证用户不受到错误信息的误导。
需要指出的是,许多浏览器会忽略该事件并自动关闭页面无需用户的确认。火狐浏览器在配置页面about:config设有一个dom.disable_beforeunload的开关变量用于开启这个功能。

  1. 要重新加载该网站吗?
    注意:可以通过检查e.clientX、e.clientY判断用户是否点击,右上角关闭浏览器的,但是实践发现 只有 IE6,IE7,IE8 能获取得到具体数值,其他浏览器均为 undefined。

  2. 要离开此网站吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
window.onbeforeunload = function (e) {
console.log(e)
return 'close'
}
window.onbeforeunload = function (e) {
e = e || window.event;
// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = '关闭提示';
}
<!-- alert("你取消了离开网页!") -->
<!-- Blocked alert('你取消了离开网页!') during beforeunload. -->
// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
return '关闭提示';
};

returnValue

window.onbeforeunload
各浏览器对 onbeforeunload 事件的支持与触发条件实现有差异

兼容性

  1. IE、Chrome、Safari 完美支持
  2. Firefox 不支持文字提醒信息
  3. Opera 不支持

问题

  1. IE6,IE7 使用 onbeforeunload 遇到的bug
    凡是<a>标签 都会触发 onbeforeunload事件 包括 href=”javascript:void(0)” 这种。
    在IE6,IE7 下面 点击 里面的 a 标签,蛋疼的事情就发生了。
    解决方法:给这 a标签的 父级 添加 onclick=function(){return false} 即可,不过添加了这个之后 要确保 父级里面没有 input type=”checkbox” 的标签,否则会导致其无效不可点击。

判断页面是否关闭

1
2
3
4
5
6
7
8
9
10
11
12
window.onbeforeunload = function(e) {
e = e || window.event;
if (e) {
e.returnValue = '关闭提示';
}
setTimeout(beforeloadResult, 50)
return '确认离开网页?'
}
function beforeloadResult () {
localStorage.setItem('beforeloadResult', true)
alert("你取消了离开网页!")
}
  1. 思考通过用户触发onbeforeunload,滞后执行beforeloadResult,注入localStorage(如果关闭页面beforeloadResult,将不会执行),用户可以选择取消。
  2. 由于javascript的阻塞性质,不管我们这个setTimeout设定的时间间隔有多小(太小如0貌似不行),都要等到这个我们把这个alert关闭才会执行。如果我们时间间隔够小,那么一关闭alert就会执行了。

问题:

  1. onbeforeunload在刷新、关闭页面都和触发,
  2. 在火狐浏览器下,即使页面关闭了,也依然会执行beforeloadResult();但是并没有暂停脚本执行,没有达到理想的效果。可能是因为网页关闭的时间比 执行 beforeloadResult() 所花的时间要长的原因。
    1. 创建一个定时任务,这个定时任务的功能是创建另一个定时任务。
    2. 在另一个定时任务里,定时执行我们的beforeloadResult();这个定时任务开始计算时间的时候,就是我们确定(或取消)关闭网页的时候。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
window.onload = function(e) {
if (localStorage.getItem('beforeloadResult')) {
// 页面刷新
alert(localStorage.getItem('beforeloadResult'))
localStorage.removeItem('beforeloadResult')
}
}
window.onbeforeunload = function(e) {
if (localStorage.getItem('beforeloadResult')) {
localStorage.removeItem('beforeloadResult')
}
e = e || window.event
// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = '关闭提示'
}
// 清除localStorage
// 火狐浏览器BUG
setTimeout(function() {
setTimeout(beforeloadResult, 50)
}, 50)
return '确认离开网页?'
}
function beforeloadResult () {
localStorage.setItem('beforeloadResult', true)
console.log(true)
alert("你取消了离开网页!")
}
测试了Chrome

before-unload

before-unload
不同的条件判断引用onbeforeunload

兼容性

  1. Firefox (Gecko) >= 1
  2. Chrome >= 1
  3. Internet Explorer >= 4
  4. Opera >= 12
  5. Safari (Webkit) >= 3

unload

浏览器卸载页面后执行的事件(由于种种限制,很少被使用)

1
2
3
4
//JS document
window.onunload = function() {
alert("unload is work")
}

兼容性

  1. IE6,IE7,IE8 中 刷新页面、关闭浏览器之后、页面跳转之后都会执行;
  2. IE9 刷新页面 会执行,页面跳转、关闭浏览器不能执行;
  3. firefox(包括firefox3.6) 关闭标签之后、页面跳转之后、刷新页面之后能执行,但关闭浏览器不能执行;
  4. Safari 刷新页面、页面跳转之后会执行,但关闭浏览器不能执行;
  5. Opera、Chrome 任何情况都不执行。

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. DOMContentLoaded
    1. 1.1. DOMContentLoaded 和脚本
      1. 1.1.1. 两处不同
    2. 1.2. 浏览器的自动补全
  2. 2. load
  3. 3. readyState
    1. 3.1. readystatechange
  4. 4. unload
  5. 5. beforeunload
    1. 5.1. 兼容性
    2. 5.2. 问题
    3. 5.3. 判断页面是否关闭
    4. 5.4. before-unload
      1. 5.4.1. 兼容性
  6. 6. unload
    1. 6.1. 兼容性
,