仅在元素完全加载时执行一次的函数
Function that executes once and only when an element is fully loaded
我很难让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";
通常不是将内容附加到元素的好方法。以下是浏览器执行此操作时的操作:
- 旋转元素和它构建的 HTML 字符串以提供给 JavaScript 层的任何后代元素。
- 从元素中删除所有内容,该元素具有删除后代元素上的任何事件处理程序的副产品。
- 分析 HTML 字符串并为其生成新的节点和元素。
所以需要做一些工作,还有清除事件处理程序的可能性。如果要添加新的子元素,请查看使用 createElement
和 appendChild
。如果要添加更多文本内容,请查看 createTextNode
和 appendChild
。
原答案:
如果你给你的元素一个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
,大概你以某种方式找到了它(querySelector
,querySelectorAll
等(,因此会知道你是否找到了它,并能够安排下一次检查。
可能值得对其进行限制,例如:
(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 并且该元素不再存在,则在测试时会看到错误,并提醒您更新代码。
编辑:现在你已经展示了你的代码,它有一些问题。
例如,getElementsByClassName()
返回一个数组,因此您无法执行此操作:
var headerElement = document.getElementsByClassName("flex-module-header");
if (headerElement.innerHTML == undefined)
您必须这样做:
var headerElement = document.getElementsByClassName("flex-module-header");
if (!headerElement || headerElement.length == 0 || headerElement[0].innerHTML == undefined)
问题中提供代码之前的原始答案:
如果你向我们展示了整个问题,我们可能会想出一些更优雅的东西,但根据你告诉我们的内容,我们现在只能建议钝力方法:
(function() {
var item, cnt = 0;
var pollTimer = setInterval(function() {
++cnt;
if (!item) {
// cache the item if found so future checks will be faster
item = document.getElementById("testObject");
}
if (item && item.innerHTML != "") {
// the item has innerHTML now, you can process it
// with code here
clearInterval(pollTimer);
} else {
if (cnt > 100) {
// if not found after 100 checks (20 seconds)
// then stop looking so we don't keep going forever
clearInterval(pollTimer);
}
}
}, 200);
}){};
- 使用每500ms运行一次的jquery函数是个好主意吗
- Javascript函数,需要每隔30秒递减一次
- 当元素可见时,jQuery滚动函数会触发一次
- 使函数只运行一次(Javascript)
- 如何在Javascript中设置函数在上一次结束时启动
- 运行“;非“;单击另一个函数中的函数仅一次
- 角函数每秒钟增加一次
- JavaScript只有在最后一次被调用时才运行函数
- 如何只使用一次window.onload函数
- 如何每 10 秒调用一次 JS 函数,然后以角度激活一个函数
- 节点 js 在启动时调用函数一次
- 有人可以帮助我调试带有addClass和removeClass函数的“每个会话一次”cookie吗?
- 如何在 window.setInterval 中每分钟运行一次 getJSON 函数
- 一次将多个对象传递给函数参数
- 就绪函数上的指令只能执行一次
- 一段时间后调用函数,但只调用一次
- 如何加载一个html页面并在其中只需单击一次即可运行函数
- Javascript只使用setInterval()调用一个子函数一次
- 元素在JavaScript函数中只更改过一次
- 函数只更改一次内容