Javascript 只在元素完全加载时执行一次的函数
让JavaScript函数只在DOM元素完全加载时执行一次有点困难。我尝试了无数次组合Javascript 只在元素完全加载时执行一次的函数,javascript,element,execute,exists,Javascript,Element,Execute,Exists,让JavaScript函数只在DOM元素完全加载时执行一次有点困难。我尝试了无数次组合setIntervals、seTimeouts、FOR循环、IF语句、WHILE循环等,但都一无所获 我确实成功地让它工作了一次,但它是偶然的,因为我只能通过将函数延迟2秒(这不好,因为无法确切地知道加载需要多长时间)和快速地反复启动相同的函数来让它工作,这也不好 我只需要一些东西来不断地扫描页面,以判断某个元素是否存在并包含内容(innerHTML!=undefined,或者其他什么),加载一块代码后立即执行
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);
}
}
完成的代码
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
没有innerHTML
属性。如果您想要第二个匹配元素,请使用[1]
获取它,然后测试是否返回了某些内容(或者如果您愿意,可以使用.length>1
首先检查,但是节点列表
记录为对于不存在的索引返回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+=“标记”代码>通常不是向元素追加内容的好方法。以下是浏览器在执行此操作时所做的操作:
旋转元素和它拥有的任何子元素,构建一个HTML字符串以提供给JavaScript层
从元素中删除所有内容,其副产品是删除子元素上的任何事件处理程序
解析HTML字符串并为其构建新节点和元素
所以需要做一点工作,而且可能会清除事件处理程序。如果要添加新的子元素,请查看使用and。如果要添加更多文本内容,请查看并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
返回一个元素,而不是一个元素NodeList
没有innerHTML
属性。如果您想要第二个匹配元素,请使用[1]
获取它,然后测试是否返回了某些内容(或者如果您愿意,可以使用.length>1
首先检查,但是节点列表
记录为对于不存在的索引返回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+=“标记”代码>通常不是向元素追加内容的好方法。以下是浏览器在执行此操作时所做的操作:
旋转元素和它拥有的任何子元素,构建一个HTML字符串以提供给JavaScript层
从元素中删除所有内容,其副产品是删除子元素上的任何事件处理程序
解析HTML字符串并为其构建新节点和元素
所以需要做一点工作,而且可能会清除事件处理程序。如果要添加新的子元素,请查看使用and。如果要添加更多文本内容,请查看并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)
问题中提供代码之前的原始答案:
如果你向我们展示了整个问题,我们可能会想出更优雅的方法,但根据你告诉我们的,