javascript - 仅当元素完全加载时执行一次的函数

标签 javascript element execute exists

我在让 JavaScript 函数仅在 DOM 元素完全加载时执行一次时遇到了一些困难。我尝试了无数种 setInterval 的组合s,seTimeout s,FOR循环,IF声明,WHILE循环等却一事无成。

我确实设法让它工作了一次,但它是偶然的,因为我只能通过将功能延迟 2 秒来让它工作(这不好,因为不知道到底需要多长时间)需要加载)并一遍又一遍地快速重新触发相同的功能,这也不好。

我只需要不断扫描页面来判断某个元素是否存在并包含内容( innerHTML != undefined 或其他内容),在加载后立即执行一段代码(并且仅一次),然后停止扫描页面。

有没有人找到办法做到这一点?另外,我需要 JavaScript,而不是 jQuery。

谢谢。

原始代码

function injectLink_Bridge(){
    setTimeout(function(){
        injectLink();
    }, 2000);
}

function injectLink(){
    var headerElement = document.getElementsByClassName("flex-module-header");

    if (headerElement.innerHTML == undefined) {
        console.log("Element doesn't exist. Restarting function");

        setTimeout(function(){
            injectLink_Bridge(); //I can't remember if the bridge is necessary or not
        }, 2000); 
    } else {
        console.log("Element exists. Injecting");

        setTimeout(function(){
            headerElement[1].innerHTML += "code" //Inject code into the second instance of the class-array
        }, 2000);
    }
}

完成代码

function injectLink(){
    var headerElement = document.getElementsByClassName("flex-module-header")[1]; //Get the second instance

    if(headerElement && headerElement.innerHTML != ""){
        console.log("Element exists and has content. Injecting code...");
        headerElement.innerHTML += "code"; //Currently revising, due to T.J. Crowder's side-note
    } else {
        console.log("Element doesn't exist or has no content. Refiring function...");
        setTimeout(injectLink, 250);
    }
}

最佳答案

在发布代码后更新了答案:

getElementsByClassName 返回 NodeList ,不是一个元素; NodeList 没有 innerHTML 属性。如果您想要第二个匹配元素,请使用 [1] 获取它,然后测试您是否得到了返回的内容(或者如果您愿意,可以使用 .length > 1首先检查,但 NodeList 被记录为对于不存在的索引返回 null)。此外,在将现有函数传递给 setTimeout 时,您不需要对现有函数进行函数包装。所以:

function injectLink(){
    var headerElement = document.getElementsByClassName("flex-module-header")[1];

    if (!headerElement) {
        console.log("Element doesn't exist. Restarting function");

        setTimeout(injectLink, 2000); 
    } else {
        console.log("Element exists. Injecting");

        // Do you really want a further two second delay?
        setTimeout(function(){
            headerElement.innerHTML += "code"; //Inject code into the second instance of the class-array
        }, 2000);
    }
}

旁注:使用 .innerHTML += "markup"; 通常不是将内容附加到元素的好方法。当您执行此操作时,浏览器将执行以下操作:

  1. 遍历该元素及其所有后代元素,构建 HTML 字符串以提供给 JavaScript 层。
  2. 拆除元素中的所有内容,其副产品是删除后代元素上的所有事件处理程序。
  3. 解析 HTML 字符串并为其构建新的节点和元素。

这需要一些工作,而且还有可能清除事件处理程序。如果您要添加新的子元素,请查看使用 createElementappendChild 。如果您要添加更多文本内容,请查看 createTextNodeappendChild

<小时/>

原始答案:

如果您为元素指定一个id(尽管无论您如何查找元素,相同的概念都适用),您可以执行以下操作:

(function() {
    setTimeout(check, 0);
    function check() {
        var elm = document.getElementById('theId');
        if (!elm) {
            setTimeout(check, 250); // Check again in a quarter second or so
            return;
        }

        // Use the element
    }
})();

在那里,我们几乎立即启动第一次检查,如果我们没有找到该元素,我们会安排 250 毫秒后再次检查。因为如果前一次检查没有找到该元素,我们只会安排下一次检查,因此我们只根据需要循环多次以找到该元素。

如果该元素没有 id,那么您可能会以某种方式找到它(querySelectorquerySelectorAll等),这样就会知道您是否找到它并能够安排下一次检查。

可能值得对其进行限制,例如:

(function() {
    var start = new Date();
    setTimeout(check, 0);
    function check() {
        var elm = document.getElementById('theId');
        if (!elm) {
            if (new Date() - start > 5000) { // More than five seconds
                throw "Couldn't find the element";
            }
            setTimeout(check, 250); // Check again in a quarter second or so
            return;
        }

        // Use the element
    }
})();

...因此,如果您更改了 HTML 并且该元素不再存在,您在测试时会看到错误,并会提醒您更新代码。

关于javascript - 仅当元素完全加载时执行一次的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10380678/

相关文章:

javascript - 使用 ionic 触摸事件更新 moment.js 持续时间

javascript - 在 Visual Studio 2013 的 Windows Phone javascript 模板中启用状态栏

html - Float 不适用于 Twitter-Bootstrap

jquery - 获取索引 REVERSED 中的元素位置

php - 插入不起作用,准备、绑定(bind)和执行,但不起作用

c# - 如何创建一段 C#.NET 脚本让 MySql 服务器执行 MySql 脚本?

javascript - 我使用 Promise 和 async 哪里出错了?

javascript - 调整后的字体大小如何延续到随后访问的页面?

java - Java Swing 中元素的用途及其与 StyledDocument 和段落的关系

sql - 将完整结果集传递给数据流任务 SSIS