簡體   English   中英

確定何時加載 innerHTML 的事件

[英]Event to determine when innerHTML has loaded

是否可以確定何時加載了 innerHTML? 我不確定這是否是同步操作。 我假設“構建 DOM”是同步的,但加載標簽、內容等不是。

所以簡而言之 - 有沒有辦法在 innerHTML 完成加載時獲取事件?

謝謝!

您需要使用DOM Mutation Observers ,目前僅適用於Chrome 和 Firefox 它們取代了破壞性能的 DOM 突變事件。

示例代碼,來自 HTML5Rocks:

var insertedNodes = [];
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations) {
 mutations.forEach(function(mutation) {
   for (var i = 0; i < mutation.addedNodes.length; i++)
     insertedNodes.push(mutation.addedNodes[i]);
 })
});

observer.observe(document, { childList: true });
console.log(insertedNodes);

這是 DOM4 規范 請不要使用setTimeout()黑客。 :)

由於通過innerHTML 添加的img 元素確實觸發了它們的onload 事件,您可以在插入innerHTML 的原始代碼的末尾添加一個小圖像,並且在它們的onload 事件中您可以調用function。 您也可以刪除那里的圖像。

<img src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' onload='hasLoadedFunc();this.parentNode.removeChild(this);'>

JSFiddle 示例

src='data:image' 代碼在這里很有用,因為不需要特定的圖像。

我在另一個答案中找到了這個解決方案,我只是找不到它。 找到參考后,我將編輯此解決方案。

 var waitUntil = function (fn, condition, interval) {
    interval = interval || 100;

    var shell = function () {
            var timer = setInterval(
                function () {
                    var check;

                    try { check = !!(condition()); } catch (e) { check = false; }

                    if (check) {
                        clearInterval(timer);
                        delete timer;
                        fn();
                    }
                },
                interval
            );
        };

    return shell;
};

像這樣使用它:

waitUntil(
  function () {
    // the code you want to run here...
  },
  function() {
    // the code that tests here... (return true if test passes; false otherwise)
    return !!(document.getElementById('<id of the div you want to update>').innerHTML !== '');
  },
  50 // amout to wait between checks
)();

如果您替換整個文檔 HTML,那么@zahanm的答案似乎不起作用,這正是我所需要的。 所以我不得不退回到setInterval 基於@shawndumas的回答,我使用Promise創建了一種更現代的方法:

function waitUntilSelectorExist(selector, interval = 100, timeout = 20000) {
    let intervalId;
    let elapsed = 0;

    let promise = new Promise(function(resolve, reject) {
        intervalId = setInterval(() => {
            let element = document.querySelector(selector);
            if (element !== null) {
                clearInterval(intervalId);
                resolve(element);
            }
            elapsed += interval;
            if (elapsed > timeout) {
                clearInterval(intervalId);
                reject(`The selector ${selector} did not enter within the ${timeout}ms frame!`);
            }
        }, interval);
    });

    return promise;
}

我也使用querySelector代替,因此您可以搜索您喜歡的任何選擇器,無論是.class#id等。

如果 function 曾經在文檔中找到querySelector ,則Promise將解析,因此您可以將其與新的await關鍵字一起使用。

(async() => {
    try {
        await waitUntilSelectorExist("#test");
        console.log("Do stuff!");
    } catch (error) {
        console.warn(error); // timeout!
    }
})();

當然,如果您真的只是更改文檔中的某些元素,您也可以在Promise中包含MutationObserver

function waitUntilSelectorExist(selector) {
    let MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

    let promise = new Promise(function(resolve) {
        let observer;
        observer = new MutationObserver(function(mutations) {
            let element = document.querySelector(selector);
            if (element !== null) {
                observer.disconnect();
                resolve();
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    });
    
    return promise;
}

如果您的問題是等到元素上的 innerHTML 已完全呈現和繪制,例如測量元素的最終大小,請在頂級或異步函數中使用此代碼:

await YieldForFrame();
await YieldForFrame();

以下代碼是您程序的一部分:

function YieldForFrame()
    {
    // Create Promise for use with 'await'
    return new Promise(function(resolve, reject)
        {
        requestAnimationFrame(resolve);
        });
    } // YieldForFrame

如何創建一個容器 div 並向其添加一個 onload 事件處理程序。

var container = document.createElement('div');
container.addEventListener('load', function() {
    // Do something here
}, false);
container.innerHTML = '<h1>Here comes my HTML</h1>';
document.getElementById('someId').appendChild(container);

您是否嘗試過使用window.onload事件? 此事件在整個頁面完全加載時觸發,包括其所有內容,如圖像、腳本、內框等。

PS 如果你使用 JQuery 庫,那么你可以使用他們的$(window).load事件包裝器。

是的,你可以這樣做:

window.document.getElementById("Testing").innerHTML = 
"<img src='test.jpg' width='200' height='400'>";
alert('test');

javascript 將按順序執行,因此一旦加載了您的 innerHTML,警報將關閉 go。

另外,看看Javascript 執行 Model

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM