1 回答

TA貢獻1809條經驗 獲得超8個贊
事件偵聽器和獲取請求可能會發生一些潛在的情況。其他讀者請注意,截至撰寫本文時(2020 年 11 月),僅 Chrome/Chromium、Edge 和 Opera 支持 iframe 中的延遲加載。
這個答案針對的是還想使用延遲加載來動態加載內容的提問者。如果只關心發出單個網絡請求,則可以通過 fetch 請求并src
通過 Blob 或數據 URI 或通過 或使用 Service Workers 設置 iframe 來完成srcdoc
(下面將對此進行探討)。
添加事件偵聽器之前可能加載的幀
您可以在聲明框架后將事件偵聽器添加到框架中,如果在評估腳本之前加載框架(如果已緩存,則可能會出現這種情況),這可能會產生問題。
contentWindow
通常,您可以通過或屬性查看您的框架是否已加載contentDocument
,如果是,則在這些框架上運行初始化代碼,但由于該框架是沙盒的,因此無法訪問這些屬性。相反,您可以做的是提前聲明您的處理程序,然后在創建 iframe 時聲明它:
async function loader(frame) {
? ? console.log(frame.src);
? ? // ...
}
<iframe?src="frame.html"?loading="lazy"?sandbox=""?onload="loader(this)"></iframe>
在獲取請求中使用同源
根據 MDN,only-if-cached
只能在mode
設置為 時使用same-origin
,這在您的情況下應該沒問題,因為您說框架是同源的。獲取請求將類似于:
await?fetch(src,?{?mode:?'same-origin',?cache:?'only-if-cached'?});
結果
main.html
<!doctype html>
<html>
? <head>
? ? <meta charset="utf-8" />
? ? <style>
? ? ? .spacer {
? ? ? ? height: 200vh;
? ? ? ? background: lightgray;
? ? ? ? text-align: center;
? ? ? }
? ? </style>
? ? <script>
? ? ? async function loader(frame) {
? ? ? ? var sourceCodeElementId = frame.dataset.code;
? ? ? ? var sourceCodeElement = document.getElementById(sourceCodeElementId);
? ? ? ? var response = await fetch(frame.src, {
? ? ? ? ? mode: 'same-origin',
? ? ? ? ? cache: 'only-if-cached'
? ? ? ? });
? ? ? ? if (response.status === 504) {
? ? ? ? ? // if it didn't load via cache, just get it normally
? ? ? ? ? response = await fetch(frame.src);
? ? ? ? }
? ? ? ? var text = await response.text();
? ? ? ? sourceCodeElement.textContent = text;
? ? ? }
? ? </script>
? </head>
? <body>
? ? <div class="spacer">Scroll Down</div>
? ? <iframe src="frame.html"
? ? ? ? loading="lazy"
? ? ? ? data-code="frame-source-code"
? ? ? ? sandbox=""
? ? ? ? onload="loader(this)">
? ? </iframe>
? ? <pre id="frame-source-code"></pre>
? </body>
</html>
樣本frame.html
<!doctype html>
<html>
Frame
</html>
可選/替代地使用 Service Worker
如果問題是圍繞網絡請求,您可以使用Service Workers,作為上述修復的替代方案或補充。讓它們啟動并運行需要一些工作,但它們可以讓您更好地控制網絡請求。緩存文件是一個常見的教程,因此如果您走這條路,您應該能夠找到相當數量的資源。
添加回答
舉報