JS的页面生命周期事件
JS生命周期事件
-
DOMContentLoaded, 浏览器完成HTML的加载, 并构建DOM树,但是css和img等外部资源尚未加载完成。注意:这里的外部资源指的是需要发送http请求获得的资源,而不是自己文件中的资源
-
load, 浏览器加载完所有资源, 包括HTML文档, 图片, 样式等
-
beforeunload, 用户即将离开, 用来检查用户是否保存了修改, 并询问是否真的要离开
-
unload, 用户几乎已经离开, 但是可以启动一些操作, 比如发送统计数据
1. DOMContentLoaded
DOMContentLoaded 事件发生在 document 对象上, 必须使用document对象上,DOMContentLoaded会等待所有script标签执行完毕之后再执行。
<h1>Hello, DOMContentLoaded!</h1>
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
<script>
function testReady() {
alert('DOM树已经构建完毕!')
alert(`此时图片的大小为${img.offsetWidth}*${img.offsetHeight}`)
}
document.addEventListener('DOMContentLoaded',testReady);
</script>
2. window.onload
这个事件表示,页面已经加载完了所有的HTML、DOM树和样式图片等资源。
<script>
window.onload = function test() {
alert('HTML、图片、样式等资源均加载完毕');
alert(`图片的大小是${img.offsetWidth}*${img.offsetHeight}`);
}
</script>
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
3. window.onunload
当访问者离开页面时,window 对象上的 unload 事件就会被触发。我们可以在那里做一些不涉及延迟的事件,比如关闭相关的弹出窗口
可以在用户离开时, 使用unload
事件发送我们想要保存在服务器上的数据 参考https://w3c.github.io/beacon/, 可以使用navigator.sendBeacon(url, data)
方法来发送数据
let analyticsData = { /* 收集了数据的对象 */ };
window.addEventListener("unload", function() {
navigator.sendBeacon("/analytics", JSON.stringify(analyticsData));
};
- 请求以 POST 方式发送。
- 我们不仅能发送字符串,还能发送表单以及其他格式的数据,在 文章 "fetch-basics" 未找到 章节我们已有说明,但是通常情况下它是一个字符串化的对象。
- 数据大小限制在 64kb。 当 sendBeacon 请求完成的时候,浏览器可能已经离开了文档,所以就没办法获取服务器的响应数据
4. window.onbeforeunload
如果访问中触发了离开页面的导航或试图关闭窗口,beforeunload
将要求提供更多的确认信息 如果我们取消该事件,浏览器将会询问用户是否确定
window.onbeforeunload = function() {
return false
}
<h1>Hello, DOMContentLoaded!</h1>
<a href="http://www.baidu.com">点击跳转到百度</a>
<script>
window.addEventListener('beforeunload', (event) => {
// Cancel the event as stated by the standard.
event.preventDefault();
// Chrome requires returnValue to be set.
event.returnValue = 'Write something clever here..';
});
</script>
5. readyState
document.readyState
属性为我们提供了一些关于当前加载状态的信息(判断文档是否加载完毕)
-
loading
—— 文档正在被加载。 -
interactive
—— 可交互,但是一些图片资源和样式仍在加载中。 -
complete
—— 文档被全部读取,并且所有的资源(图像之类的)都被加载。
function work() { /*...*/ }
if (document.readyState == 'loading') {
// 正在加载,等待事件
document.addEventListener('DOMContentLoaded', work);
} else {
// DOM 已经准备就绪!
work();
}
Dom生命周期
文档对象模型 (DOM) 将 web 页面与到脚本或编程语言连接起来。通常是指 JavaScript,但将 HTML、SVG 或 XML 文档建模为对象并不是 JavaScript 语言的一部分。DOM模型用一个逻辑树来表示一个文档,树的每个分支的终点都是一个节点(node),每个节点都包含着对象(objects)。DOM的方法(methods)让你可以用特定方式操作这个树,用这些方法你可以改变文档的结构、样式或者内容。节点可以关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。
Dom变动事件的分类有7种,最常用的浏览器支持最多的有前3种:
- DOMSubtreeModified:在DOM结构中发生任何变化时触发;
- DOMNodeInserted:在一个节点作为子节点被插入到另一个节点中时触发;
- DOMNodeRemoved:在节点从其父节点中被移除时触发;
- DOMNodeInsertedIntoDocument:在一个节点被直接插入文档中或者通过子树间接插入文档后触发。在DOMNodeInserted之后触发;
- DOMNodeRemovedFromDocument:在一个节点被直接从文档中删除或通过子树间接从文档中移除之前触发。在DOMNodeRemoved之后触发。
- DOMAttrModified:在特性被修改之后触发;
- DOMCharacterDataModified:在文本节点的值发生变化的时候触发。
删除节点
首先触发的是DOMNodeRemoved事件,它对应的event对象中的target属性值是被删除的节点,relatedNode属性值是被删除节点的父节点,该事件会冒泡;
其次出发的是DOMNodeRemovedFromDocument事件,它对应的event对象中的target属性值为指定的被删除的子节点。只有绑定到它的子节点上才能被触发。
最后触发的是DOMSubtreeModified事件。这个事件对应event对象中的target属性是被移除节点的父节点。
// 获取第一子节点(找到第一个不为空的节点)
function getFirstChild(obj){
var first = obj.firstChild;
while(first.nodeType != 1){
first = first.nextSibling;
}
return first;
}
EventUtil.addHandler(window,"load",function(event){
var list = document.getElementById('myList');
var btn = document.getElementById("mbtn");
EventUtil.addHandler(document,"DOMNodeRemoved",function(event){
console.log(event.type); //1:DOMNodeRemoved
console.log(event.target); //2:ul节点,即被删除的节点
console.log(event.relatedNode); //3:body节点,即被删除节点的父节点
});
EventUtil.addHandler(getFirstChild(list),"DOMNodeRemovedFromDocument",function(event){
console.log(event.type) //4:DOMNodeRemovedFromDocument
console.log(event.target) //5:li节点,即<li>item1</li>
});
EventUtil.addHandler(document,"DOMSubtreeModified",function(event){
console.log(event.type); //6:DOMSubtreeModified
console.log(event.target); //7:body节点,即被删除节点的父节点
})
EventUtil.addHandler(btn,'click',function(event){
list.parentNode.removeChild(list); //
})
})
dom节点添加
在使用appendChild()、replaceChild()或insertBefore()向DOM中插入节点的时候:
首先触发DOMInserted事件,它对应的event对象中的target属性为添加的节点,relateNode属性对应被添加节点的父节点。(可冒泡);
其次触发的是DOMNodeInsertedIntoDocument事件,它对应的event对象中的target属性是添加的节点,只有指定给一个子节点的事件处理程序才会被调用
最后出发的是DOMSubtreeModified事件,它对应的event对象长得target属性值是新节点的父节点。
function getFirstChild(obj){ // 获取第一子节点(找到第一个不为空的节点)
var first = obj.firstChild;
while(first.nodeType != 1){
first = first.nextSibling;
}
return first;
}
EventUtil.addHandler(window,"load",function(event){
var list = document.getElementById('myList');
var btn = document.getElementById("mbtn");
var item4 = document.createElement('li');
var item4Text = document.createTextNode('item4');
EventUtil.addHandler(document,"DOMNodeInserted",function(event){
console.log(event.type); //1:DOMNodeInserted
console.log(event.target); //2:li节点,即被添加的节点
console.log(event.relatedNode); //3:ul节点,即被添加节点的父节点
});
EventUtil.addHandler(item4,"DOMNodeInsertedIntoDocument",function(event){
console.log(event.type); //4:DOMNodeInsertedIntoDocument
console.log(event.target); //5:li节点,即被添加的节点<li>item4</li>
});
EventUtil.addHandler(document,"DOMSubtreeModified",function(event){
console.log(event.type); //6:DOMSubtreeModified
console.log(event.target); //7:ul节点,即被触发节点的父节点
})
EventUtil.addHandler(btn,'click',function(){
item4.appendChild(item4Text); getFirstChild
list.replaceChild(item4,getFirstChild(list));
});
})