日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

用框架的你,可能早已忽略了这些事件API

發(fā)布時(shí)間:2023/12/9 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用框架的你,可能早已忽略了这些事件API 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

DOMContentLoaded,load,beforeunload,unload

HTML 頁(yè)面的生命周期包含三個(gè)重要事件:

  • DOMContentLoaded —— 瀏覽器已完全加載 HTML,并構(gòu)建了 DOM 樹,但像 <img> 和樣式表之類的外部資源可能尚未加載完成。

  • load —— 瀏覽器不僅加載完成了 HTML,還加載完成了所有外部資源:圖片,樣式等。

  • beforeunload/unload —— 當(dāng)用戶正在離開頁(yè)面時(shí)。

每個(gè)事件都是有用的:

  • DOMContentLoaded 事件 —— DOM 已經(jīng)就緒,因此處理程序可以查找 DOM 節(jié)點(diǎn),并初始化接口。

  • load 事件 —— 外部資源已加載完成,樣式已被應(yīng)用,圖片大小也已知了。

  • beforeunload 事件 —— 用戶正在離開:我們可以檢查用戶是否保存了更改,并詢問他是否真的要離開。

  • unload 事件 —— 用戶幾乎已經(jīng)離開了,但是我們?nèi)匀豢梢詥?dòng)一些操作,例如發(fā)送統(tǒng)計(jì)數(shù)據(jù)。

我們探索一下這些事件的細(xì)節(jié)。

DOMContentLoaded

DOMContentLoaded 事件發(fā)生在 document 對(duì)象上。

我們必須使用 addEventListener 來捕獲它:

document.addEventListener("DOMContentLoaded",?ready); //?不是?"document.onDOMContentLoaded?=?..."

例如:

<script>function?ready()?{alert('DOM?is?ready');//?圖片目前尚未加載完成(除非已經(jīng)被緩存),所以圖片的大小為?0x0alert(`Image?size:?${img.offsetWidth}x${img.offsetHeight}`);}document.addEventListener("DOMContentLoaded",?ready); </script><img?id="img"?src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">

在示例中,DOMContentLoaded 處理程序在文檔加載完成后觸發(fā),所以它可以查看所有元素,包括它下面的 <img> 元素。

但是,它不會(huì)等待圖片加載。因此,alert 顯示其大小為零。

乍一看,DOMContentLoaded 事件非常簡(jiǎn)單。DOM 樹準(zhǔn)備就緒 —— 這是它的觸發(fā)條件。它并沒有什么特別之處。

DOMContentLoaded 和腳本

當(dāng)瀏覽器處理一個(gè) HTML 文檔,并在文檔中遇到 <script> 標(biāo)簽時(shí),就會(huì)在繼續(xù)構(gòu)建 DOM 之前運(yùn)行它。這是一種防范措施,因?yàn)槟_本可能想要修改 DOM,甚至對(duì)其執(zhí)行 document.write 操作,所以 DOMContentLoaded 必須等待腳本執(zhí)行結(jié)束。

因此,DOMContentLoaded 肯定在下面的這些腳本執(zhí)行結(jié)束之后發(fā)生:

<script>document.addEventListener("DOMContentLoaded",?()?=>?{alert("DOM?ready!");}); </script><script?src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"></script><script>alert("Library?loaded,?inline?script?executed"); </script>

在上面這個(gè)例子中,我們首先會(huì)看到 "Library loaded...",然后才會(huì)看到 "DOM ready!"(所有腳本都已經(jīng)執(zhí)行結(jié)束)。

不會(huì)阻塞 DOMContentLoaded 的腳本:

此規(guī)則有兩個(gè)例外:

  • 具有 async 特性(attribute)的腳本不會(huì)阻塞 DOMContentLoaded,稍后[1] 我們會(huì)講到。

  • 使用 document.createElement('script') 動(dòng)態(tài)生成并添加到網(wǎng)頁(yè)的腳本也不會(huì)阻塞 DOMContentLoaded。

  • DOMContentLoaded 和樣式

    外部樣式表不會(huì)影響 DOM,因此 DOMContentLoaded 不會(huì)等待它們。

    但這里有一個(gè)陷阱。如果在樣式后面有一個(gè)腳本,那么該腳本必須等待樣式表加載完成:

    <link?type="text/css"?rel="stylesheet"?href="style.css"> <script>//?在樣式表加載完成之前,腳本都不會(huì)執(zhí)行alert(getComputedStyle(document.body).marginTop); </script>

    原因是,腳本可能想要獲取元素的坐標(biāo)和其他與樣式相關(guān)的屬性,如上例所示。因此,它必須等待樣式加載完成。

    當(dāng) DOMContentLoaded 等待腳本時(shí),它現(xiàn)在也在等待腳本前面的樣式。

    瀏覽器內(nèi)建的自動(dòng)填充

    Firefox,Chrome 和 Opera 都會(huì)在 DOMContentLoaded 中自動(dòng)填充表單。

    例如,如果頁(yè)面有一個(gè)帶有登錄名和密碼的表單,并且瀏覽器記住了這些值,那么在 DOMContentLoaded 上,瀏覽器會(huì)嘗試自動(dòng)填充它們(如果得到了用戶允許)。

    因此,如果 DOMContentLoaded 被需要加載很長(zhǎng)時(shí)間的腳本延遲觸發(fā),那么自動(dòng)填充也會(huì)等待。你可能在某些網(wǎng)站上看到過(如果你使用瀏覽器自動(dòng)填充)—— 登錄名/密碼字段不會(huì)立即自動(dòng)填充,而是在頁(yè)面被完全加載前會(huì)延遲填充。這實(shí)際上是 DOMContentLoaded 事件之前的延遲。

    window.onload

    當(dāng)整個(gè)頁(yè)面,包括樣式、圖片和其他資源被加載完成時(shí),會(huì)觸發(fā) window 對(duì)象上的 load 事件。可以通過 onload 屬性獲取此事件。

    下面的這個(gè)示例正確顯示了圖片大小,因?yàn)?window.onload 會(huì)等待所有圖片加載完畢:

    <script>window.onload?=?function()?{?//?與此相同?window.addEventListener('load',?(event)?=>?{alert('Page?loaded');//?此時(shí)圖片已經(jīng)加載完成alert(`Image?size:?${img.offsetWidth}x${img.offsetHeight}`);}; </script><img?id="img"?src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">

    window.onunload

    當(dāng)訪問者離開頁(yè)面時(shí),window 對(duì)象上的 unload 事件就會(huì)被觸發(fā)。我們可以在那里做一些不涉及延遲的操作,例如關(guān)閉相關(guān)的彈出窗口。

    有一個(gè)值得注意的特殊情況是發(fā)送分析數(shù)據(jù)。

    假設(shè)我們收集有關(guān)頁(yè)面使用情況的數(shù)據(jù):鼠標(biāo)點(diǎn)擊,滾動(dòng),被查看的頁(yè)面區(qū)域等。

    自然地,當(dāng)用戶要離開的時(shí)候,我們希望通過 unload 事件將數(shù)據(jù)保存到我們的服務(wù)器上。

    有一個(gè)特殊的 navigator.sendBeacon(url, data) 方法可以滿足這種需求,詳見規(guī)范 https://w3c.github.io/beacon/。

    它在后臺(tái)發(fā)送數(shù)據(jù),轉(zhuǎn)換到另外一個(gè)頁(yè)面不會(huì)有延遲:瀏覽器離開頁(yè)面,但仍然在執(zhí)行 sendBeacon。

    使用方式如下:

    let?analyticsData?=?{?/*?帶有收集的數(shù)據(jù)的對(duì)象?*/?};window.addEventListener("unload",?function()?{navigator.sendBeacon("/analytics",?JSON.stringify(analyticsData)); });
    • 請(qǐng)求以 POST 方式發(fā)送。

    • 我們不僅能發(fā)送字符串,還能發(fā)送表單以及其他格式的數(shù)據(jù),在 Fetch 一章有詳細(xì)講解,但通常它是一個(gè)字符串化的對(duì)象。

    • 數(shù)據(jù)大小限制在 64kb。

    當(dāng) sendBeacon 請(qǐng)求完成時(shí),瀏覽器可能已經(jīng)離開了文檔,所以就無法獲取服務(wù)器響應(yīng)(對(duì)于分析數(shù)據(jù)來說通常為空)。

    還有一個(gè) keep-alive 標(biāo)志,該標(biāo)志用于在 fetch[2] 方法中為通用的網(wǎng)絡(luò)請(qǐng)求執(zhí)行此類“離開頁(yè)面后”的請(qǐng)求。你可以在 Fetch API[3] 一章中找到更多相關(guān)信息。

    如果我們要取消跳轉(zhuǎn)到另一頁(yè)面的操作,在這里做不到。但是我們可以使用另一個(gè)事件 —— onbeforeunload。

    window.onbeforeunload

    如果訪問者觸發(fā)了離開頁(yè)面的導(dǎo)航(navigation)或試圖關(guān)閉窗口,beforeunload 處理程序?qū)⒁筮M(jìn)行更多確認(rèn)。

    如果我們要取消事件,瀏覽器會(huì)詢問用戶是否確定。

    你可以通過運(yùn)行下面這段代碼,然后重新加載頁(yè)面來進(jìn)行嘗試:

    window.onbeforeunload?=?function()?{return?false; };

    由于歷史原因,返回非空字符串也被視為取消事件。在以前,瀏覽器曾經(jīng)將其顯示為消息,但是根據(jù) 現(xiàn)代規(guī)范[4] 所述,它們不應(yīng)該這樣。

    這里有個(gè)例子:

    window.onbeforeunload?=?function()?{return?"There?are?unsaved?changes.?Leave?now?"; };

    它的行為已經(jīng)改變了,因?yàn)橛行┱鹃L(zhǎng)通過顯示誤導(dǎo)性和惡意信息濫用了此事件處理程序。所以,目前一些舊的瀏覽器可能仍將其顯示為消息,但除此之外 —— 無法自定義顯示給用戶的消息。

    readyState

    如果我們將 DOMContentLoaded 事件處理程序設(shè)置在文檔加載完成之后,會(huì)發(fā)生什么?

    很自然地,它永遠(yuǎn)不會(huì)運(yùn)行。

    在某些情況下,我們不確定文檔是否已經(jīng)準(zhǔn)備就緒。我們希望我們的函數(shù)在 DOM 加載完成時(shí)執(zhí)行,無論現(xiàn)在還是以后。

    document.readyState 屬性可以為我們提供當(dāng)前加載狀態(tài)的信息。

    它有 3 個(gè)可能值:

    • loading —— 文檔正在被加載。

    • interactive —— 文檔被全部讀取。

    • complete —— 文檔被全部讀取,并且所有資源(例如圖片等)都已加載完成。

    所以,我們可以檢查 document.readyState 并設(shè)置一個(gè)處理程序,或在代碼準(zhǔn)備就緒時(shí)立即執(zhí)行它。

    像這樣:

    function?work()?{?/*...*/?}if?(document.readyState?==?'loading')?{//?仍在加載,等待事件document.addEventListener('DOMContentLoaded',?work); }?else?{// DOM 已就緒!work(); }

    還有一個(gè) readystatechange 事件,會(huì)在狀態(tài)發(fā)生改變時(shí)觸發(fā),因此我們可以打印所有這些狀態(tài),就像這樣:

    //?當(dāng)前狀態(tài) console.log(document.readyState);//?狀態(tài)改變時(shí)打印它 document.addEventListener('readystatechange',?()?=>?console.log(document.readyState));

    readystatechange 事件是跟蹤文檔加載狀態(tài)的另一種機(jī)制,它很早就存在了。現(xiàn)在則很少被使用。

    但是為了完整起見,讓我們看看完整的事件流。

    這是一個(gè)帶有 <iframe>,<img> 和記錄事件的處理程序的文檔:

    <script>log('initial?readyState:'?+?document.readyState);document.addEventListener('readystatechange',?()?=>?log('readyState:'?+?document.readyState));document.addEventListener('DOMContentLoaded',?()?=>?log('DOMContentLoaded'));window.onload?=?()?=>?log('window?onload'); </script><iframe?src="iframe.html"?onload="log('iframe?onload')"></iframe><img?src="http://en.js.cx/clipart/train.gif"?id="img"> <script>img.onload?=?()?=>?log('img?onload'); </script>

    此示例運(yùn)行 在 sandbox 中[5]

    典型輸出:

  • [1] initial readyState:loading

  • [2] readyState:interactive

  • [2] DOMContentLoaded

  • [3] iframe onload

  • [4] img onload

  • [4] readyState:complete

  • [4] window onload

  • 方括號(hào)中的數(shù)字表示發(fā)生這種情況的大致時(shí)間。標(biāo)有相同數(shù)字的事件幾乎是同時(shí)發(fā)生的(+- 幾毫秒)。

    • 在 DOMContentLoaded 之前,document.readyState 會(huì)立即變成 interactive。它們倆的意義實(shí)際上是相同的。

    • 當(dāng)所有資源(iframe 和 img)都加載完成后,document.readyState 變成 complete。這里我們可以發(fā)現(xiàn),它與 img.onload(img 是最后一個(gè)資源)和 window.onload 幾乎同時(shí)發(fā)生。轉(zhuǎn)換到 complete 狀態(tài)的意義與 window.onload 相同。區(qū)別在于 window.onload 始終在所有其他 load 處理程序之后運(yùn)行。

    總結(jié)

    頁(yè)面生命周期事件:

    • 當(dāng) DOM 準(zhǔn)備就緒時(shí),document 上的 DOMContentLoaded 事件就會(huì)被觸發(fā)。在這個(gè)階段,我們可以將 JavaScript 應(yīng)用于元素。

      • 諸如 <script>...</script> 或 <script src="..."></script> 之類的腳本會(huì)阻塞 ?DOMContentLoaded,瀏覽器將等待它們執(zhí)行結(jié)束。

      • 圖片和其他資源仍然可以繼續(xù)被加載。

    • 當(dāng)頁(yè)面和所有資源都加載完成時(shí),window 上的 load 事件就會(huì)被觸發(fā)。我們很少使用它,因?yàn)橥ǔo需等待那么長(zhǎng)時(shí)間。

    • 當(dāng)用戶想要離開頁(yè)面時(shí),window 上的 beforeunload 事件就會(huì)被觸發(fā)。如果我們?nèi)∠@個(gè)事件,瀏覽器就會(huì)詢問我們是否真的要離開(例如,我們有未保存的更改)。

    • 當(dāng)用戶最終離開時(shí),window 上的 unload 事件就會(huì)被觸發(fā)。在處理程序中,我們只能執(zhí)行不涉及延遲或詢問用戶的簡(jiǎn)單操作。正是由于這個(gè)限制,它很少被使用。我們可以使用 navigator.sendBeacon 來發(fā)送網(wǎng)絡(luò)請(qǐng)求。

    • document.readyState 是文檔的當(dāng)前狀態(tài),可以在 readystatechange 事件中跟蹤狀態(tài)更改:

      • loading —— 文檔正在被加載。

      • interactive —— 文檔已被解析完成,與 DOMContentLoaded 幾乎同時(shí)發(fā)生,但是在 DOMContentLoaded 之前發(fā)生。

      • complete —— 文檔和資源均已加載完成,與 window.onload 幾乎同時(shí)發(fā)生,但是在 window.onload 之前發(fā)生。


    現(xiàn)代 JavaScript 教程:開源的現(xiàn)代 JavaScript 從入門到進(jìn)階的優(yōu)質(zhì)教程。React 官方文檔推薦,與 MDN 并列的 JavaScript 學(xué)習(xí)教程[6]

    在線免費(fèi)閱讀:https://zh.javascript.info


    參考資料

    [1]

    稍后: https://zh.javascript.info/script-async-defer

    [2]

    fetch: https://zh.javascript.info/fetch

    [3]

    Fetch API: https://zh.javascript.info/fetch-api

    [4]

    現(xiàn)代規(guī)范: https://html.spec.whatwg.org/#unloading-documents

    [5]

    在 sandbox 中: https://plnkr.co/edit/ct5SNvrHCA75b2KZ?p=preview

    [6]

    React 官方文檔推薦,與 MDN 并列的 JavaScript 學(xué)習(xí)教程: https://zh-hans.reactjs.org/docs/getting-started.html#javascript-resources

    推薦閱讀

    我在阿里招前端,我該怎么幫你?(現(xiàn)在還可以加模擬面試群)
    如何拿下阿里巴巴 P6 的前端 Offer
    如何準(zhǔn)備阿里P6/P7前端面試--項(xiàng)目經(jīng)歷準(zhǔn)備篇
    大廠面試官常問的亮點(diǎn),該如何做出?
    如何從初級(jí)到專家(P4-P7)打破成長(zhǎng)瓶頸和有效突破
    若川知乎問答:2年前端經(jīng)驗(yàn),做的項(xiàng)目沒什么技術(shù)含量,怎么辦?
    若川知乎高贊:有哪些必看的 JS庫(kù)?

    末尾

    你好,我是若川,江湖人稱菜如若川,歷時(shí)一年只寫了一個(gè)學(xué)習(xí)源碼整體架構(gòu)系列~(點(diǎn)擊藍(lán)字了解我)

  • 關(guān)注若川視野,回復(fù)"pdf" 領(lǐng)取優(yōu)質(zhì)前端書籍pdf,回復(fù)"1",可加群長(zhǎng)期交流學(xué)習(xí)

  • 我的博客地址:https://lxchuan12.gitee.io?歡迎收藏

  • 覺得文章不錯(cuò),可以點(diǎn)個(gè)在看呀^_^另外歡迎留言交流~

  • 精選前端好文,伴你不斷成長(zhǎng)

    若川原創(chuàng)文章精選!可點(diǎn)擊

    小提醒:若川視野公眾號(hào)面試、源碼等文章合集在菜單欄中間【源碼精選】按鈕,歡迎點(diǎn)擊閱讀,也可以星標(biāo)我的公眾號(hào),便于查找

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的用框架的你,可能早已忽略了这些事件API的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。