函数不设置段落文本
Function not setting text of paragraph
我正在尝试使用 class rules
设置段落标记的值。它应该每 4 秒在 a、b、c 等之间切换并重复。出于某种原因,该函数根本不是 运行ning,并且 chrome 的开发人员工具中没有错误。当我用 <body onload="rulesSlideshow">
调用函数时没有任何变化。
<script type="text/javascript">
document.onload = function rulesSlideshow() {
setTimeout(setRule("a"), 4000);
setTimeout(setRule("b"), 4000);
setTimeout(setRule("c"), 4000);
setTimeout(setRule("d"), 4000);
setTimeout(setRule("e"), 4000);
rulesSlideshow();
}
function setRule(rule) {
document.querySelector("rules").innerHTML = rule;
}
</script>
<p id="rule" class="rules"></p>
编辑: 通过删除 document.onload =
并添加 <body onload="rulesSlideshow()">
我可以获得 运行 的代码(由 [=15= 提供) ]).尽管如此,我的代码还是找不到段落标记。
你有一些问题,但最大的是
- 您对
setTimeout
的调用会立即调用函数
因为您使用括号来传递参数,但是
调用函数。 setTimeout
需要函数引用
- 您的
.querySelector
无法找到具有
class 因为你的 class 名字前面没有 .
请参阅下面的内联评论以获得更清晰的解决方案(我在这里使用一秒钟以便更快地查看结果):
var el = null; // prepare to hold a reference to the output element
var vals = ["a", "b", "c", "d", "e"]; // values to enumerate
var idx = 0; // counter to keep track of how many times to call a timer
var timer = null; // will hold reference to timer
// When the document is fully parsed
document.addEventListener("DOMContentLoaded", function() {
el = document.getElementById("rule"); // set up reference to output element
timer = setTimeout(setRule, 1000); // set up the timer, don't invoke the function with ()
});
// Function to be called by timer
function setRule() {
// Check the counter to see if we still have values to enumerate
if(idx < vals.length){
// We do, so set the output element to the correct array value
el.textContent = vals[idx++];
// Call the timer again
setTimeout(setRule, 1000);
}
}
<p id="rule"></p>
您遇到三个问题:
您正在分配您的rulesSlideshow()
函数给onload
,但从未真正调用 它。您可以通过在函数末尾添加方括号 function() { ... }()
来实现此目的,创建一个 Immediately Invoked Function Expression (IIFE).
您的选择器 querySelector("rules")
实际上不会定位任何东西;您需要将带有 .
前缀的 class 指定为 .querySelector(".rules")
.
您正在将所有超时设置为 4000
。因为这些将 运行 异步 ,它们都会在 同时触发 。因此,您只会看到最终输出 (e
)。要真正 'offset' 输出,您需要将超时 设置在 内,或者使用 chained promises 以便它们按顺序 运行 。
这都可以在下面看到:
document.onload = function rulesSlideshow() {
setTimeout(function() {
setRule("a");
setTimeout(function() {
setRule("b");
setTimeout(function() {
setRule("c");
setTimeout(function() {
setRule("d");
setTimeout(function() {
setRule("e");
}, 4000);
}, 4000);
}, 4000);
}, 4000);
}, 4000);
}();
function setRule(rule) {
document.querySelector(".rules").innerHTML = rule;
}
<p id="rule" class="rules"></p>
此外,请注意您不需要在 rulesSlideshow()
本身内实际调用 rulesShowshow()
;这已从上面的代码片段中删除。
定义加载处理程序
如果您尝试通过 DOM 中的 onload 属性调用该函数,您需要调用该函数,而不仅仅是引用它;所以应该是 <body onload="rulesSlideshow()">
.
如果您更喜欢在代码中定义 onload 处理程序,请使用匿名函数:
document.onload = function() {...};
...或应用于 document.onload 的命名函数作为参考:
var rulesSlideshow = function() {...}
document.onload = rulesSlideshow; // no parens this time, since you're assigning the function to the handler here, not calling it.
要么从 DOM 属性调用处理程序,要么在代码中定义它——不要两者都做。 (最好尽可能将 javascript 与 DOM 分开,因此许多人会建议不要使用 <body onload="...">
等内联事件属性,而是在代码中定义这些处理程序-- 但是这两种技术仍然可以很好地工作。)
查询选择器
由于您要查找类名,因此需要包含“.”:
document.querySelector(".rules").innerHTML = rule;
超时
由于您所有的超时都具有相同的时间值,因此它们都会 运行 同时(或足够接近)——因此您只会看到最后一个的结果。如果您希望每次调用之间有四秒的间隔,则它们需要不同的超时值。
此外,由于 rulesSlideshow 在 运行ning 之后立即调用自身,您最终会出现堆栈溢出。这也需要一个 setTimeout(虽然因为你正在做的是让函数定期重复,用 setInterval
调用它一次可能更合适。)
setTimeout 内的函数
setTimeout 期望接收一个函数,但您将调用函数的结果传递给它。如果你不需要 setRule
上的参数,你可以使用 shorthand:
setTimeout(setRule, 4000)
但是对于参数,您将需要一个匿名包装器:
setTimeout(function() {setRule("x")}, 4000)
演示
将它们放在一起(我已将其从 onload 切换为 onclick,因为 onload 很难在堆栈片段中演示,但其余部分相同):
var rulesSlideshow = function() {
console.log("Called rulesSlideshow");
setTimeout(function() {setRule("a")}, 4000);
setTimeout(function() {setRule("b")}, 8000);
setTimeout(function() {setRule("c")}, 12000);
setTimeout(function() {setRule("d")}, 16000);
setTimeout(function() {setRule("e")}, 20000);
setTimeout(rulesSlideshow, 20000); // used same timeout as above, because there's a 4s delay before this function does anything.
}
document.onclick = rulesSlideshow;
function setRule(rule) {
console.log("setRule");
document.querySelector(".rules").innerHTML = rule;
}
(Click anywhere to start)
<p id="rule" class="rules"></p>
我正在尝试使用 class rules
设置段落标记的值。它应该每 4 秒在 a、b、c 等之间切换并重复。出于某种原因,该函数根本不是 运行ning,并且 chrome 的开发人员工具中没有错误。当我用 <body onload="rulesSlideshow">
调用函数时没有任何变化。
<script type="text/javascript">
document.onload = function rulesSlideshow() {
setTimeout(setRule("a"), 4000);
setTimeout(setRule("b"), 4000);
setTimeout(setRule("c"), 4000);
setTimeout(setRule("d"), 4000);
setTimeout(setRule("e"), 4000);
rulesSlideshow();
}
function setRule(rule) {
document.querySelector("rules").innerHTML = rule;
}
</script>
<p id="rule" class="rules"></p>
编辑: 通过删除 document.onload =
并添加 <body onload="rulesSlideshow()">
我可以获得 运行 的代码(由 [=15= 提供) ]).尽管如此,我的代码还是找不到段落标记。
你有一些问题,但最大的是
- 您对
setTimeout
的调用会立即调用函数 因为您使用括号来传递参数,但是 调用函数。setTimeout
需要函数引用 - 您的
.querySelector
无法找到具有 class 因为你的 class 名字前面没有.
请参阅下面的内联评论以获得更清晰的解决方案(我在这里使用一秒钟以便更快地查看结果):
var el = null; // prepare to hold a reference to the output element
var vals = ["a", "b", "c", "d", "e"]; // values to enumerate
var idx = 0; // counter to keep track of how many times to call a timer
var timer = null; // will hold reference to timer
// When the document is fully parsed
document.addEventListener("DOMContentLoaded", function() {
el = document.getElementById("rule"); // set up reference to output element
timer = setTimeout(setRule, 1000); // set up the timer, don't invoke the function with ()
});
// Function to be called by timer
function setRule() {
// Check the counter to see if we still have values to enumerate
if(idx < vals.length){
// We do, so set the output element to the correct array value
el.textContent = vals[idx++];
// Call the timer again
setTimeout(setRule, 1000);
}
}
<p id="rule"></p>
您遇到三个问题:
您正在分配您的
rulesSlideshow()
函数给onload
,但从未真正调用 它。您可以通过在函数末尾添加方括号function() { ... }()
来实现此目的,创建一个 Immediately Invoked Function Expression (IIFE).您的选择器
querySelector("rules")
实际上不会定位任何东西;您需要将带有.
前缀的 class 指定为.querySelector(".rules")
.您正在将所有超时设置为
4000
。因为这些将 运行 异步 ,它们都会在 同时触发 。因此,您只会看到最终输出 (e
)。要真正 'offset' 输出,您需要将超时 设置在 内,或者使用 chained promises 以便它们按顺序 运行 。
这都可以在下面看到:
document.onload = function rulesSlideshow() {
setTimeout(function() {
setRule("a");
setTimeout(function() {
setRule("b");
setTimeout(function() {
setRule("c");
setTimeout(function() {
setRule("d");
setTimeout(function() {
setRule("e");
}, 4000);
}, 4000);
}, 4000);
}, 4000);
}, 4000);
}();
function setRule(rule) {
document.querySelector(".rules").innerHTML = rule;
}
<p id="rule" class="rules"></p>
此外,请注意您不需要在 rulesSlideshow()
本身内实际调用 rulesShowshow()
;这已从上面的代码片段中删除。
定义加载处理程序
如果您尝试通过 DOM 中的 onload 属性调用该函数,您需要调用该函数,而不仅仅是引用它;所以应该是 <body onload="rulesSlideshow()">
.
如果您更喜欢在代码中定义 onload 处理程序,请使用匿名函数:
document.onload = function() {...};
...或应用于 document.onload 的命名函数作为参考:
var rulesSlideshow = function() {...}
document.onload = rulesSlideshow; // no parens this time, since you're assigning the function to the handler here, not calling it.
要么从 DOM 属性调用处理程序,要么在代码中定义它——不要两者都做。 (最好尽可能将 javascript 与 DOM 分开,因此许多人会建议不要使用 <body onload="...">
等内联事件属性,而是在代码中定义这些处理程序-- 但是这两种技术仍然可以很好地工作。)
查询选择器
由于您要查找类名,因此需要包含“.”:
document.querySelector(".rules").innerHTML = rule;
超时
由于您所有的超时都具有相同的时间值,因此它们都会 运行 同时(或足够接近)——因此您只会看到最后一个的结果。如果您希望每次调用之间有四秒的间隔,则它们需要不同的超时值。
此外,由于 rulesSlideshow 在 运行ning 之后立即调用自身,您最终会出现堆栈溢出。这也需要一个 setTimeout(虽然因为你正在做的是让函数定期重复,用 setInterval
调用它一次可能更合适。)
setTimeout 内的函数
setTimeout 期望接收一个函数,但您将调用函数的结果传递给它。如果你不需要 setRule
上的参数,你可以使用 shorthand:
setTimeout(setRule, 4000)
但是对于参数,您将需要一个匿名包装器:
setTimeout(function() {setRule("x")}, 4000)
演示
将它们放在一起(我已将其从 onload 切换为 onclick,因为 onload 很难在堆栈片段中演示,但其余部分相同):
var rulesSlideshow = function() {
console.log("Called rulesSlideshow");
setTimeout(function() {setRule("a")}, 4000);
setTimeout(function() {setRule("b")}, 8000);
setTimeout(function() {setRule("c")}, 12000);
setTimeout(function() {setRule("d")}, 16000);
setTimeout(function() {setRule("e")}, 20000);
setTimeout(rulesSlideshow, 20000); // used same timeout as above, because there's a 4s delay before this function does anything.
}
document.onclick = rulesSlideshow;
function setRule(rule) {
console.log("setRule");
document.querySelector(".rules").innerHTML = rule;
}
(Click anywhere to start)
<p id="rule" class="rules"></p>