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));
        });
    })
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容