确定innerHTML何时加载的事件

时间:2011-08-09 18:53:09

标签: javascript

是否可以确定何时加载了innerHTML? 我不确定它是否是同步操作。我假设'构建DOM'是同步的,但加载标签,内容等不是。

简而言之 - 当innerHTML完成加载时,是否有办法获取事件?

谢谢!

7 个答案:

答案 0 :(得分:17)

您需要使用DOM Mutation Observers,目前只适用于Chrome and Firefox。 它们取代了杀死性能的DOM Mutation Events。

示例代码,来自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 spec。 请不要使用setTimeout()黑客。 :)

答案 1 :(得分:1)

因为通过innerHTML添加的img元素会触发它们的onload事件,所以你可以在插入innerHTML的原始代码的末尾添加一个小图像,并且在它们的onload事件中你可以调用一个函数。你也可以在那里删除图像。

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

JSFiddle sample

src ='data:image'代码在这里很有用,因为不需要特定的图像。

我在另一个答案中找到了这个解决方案,我找不到它。一旦找到参考,我将编辑此解决方案。

答案 2 :(得分:0)

 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
)();

答案 3 :(得分:0)

如果您替换整个文档 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 等。

如果函数在文档中找到 querySelectorPromise 将解析,因此您可以将它与新的 await 关键字一起使用。

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

当然,如果您真的只是更改文档中的某些元素,您也可以将 MutationObserver 包裹在 Promise 中:

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;
}

答案 4 :(得分:-2)

是的,你可以这样做:

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

javascript将按顺序执行,因此一旦加载了innerHTML,警报就会消失。

另外,请查看Javascript Execution Model

答案 5 :(得分:-2)

如何创建容器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);

答案 6 :(得分:-2)

您是否尝试过使用window.onload事件?整个页面完全加载时会触发此事件,包括图像,脚本,内部框架等所有内容。

P.S。如果您使用JQuery库,那么您可以使用他们的$(window).load事件包装器。