功能不设置段落文本

时间:2018-02-27 22:06:47

标签: javascript html function innerhtml

我正在尝试使用类rules设置段落标记的值。它应该每4秒在a,b,c等之间切换并重复。出于某种原因,该功能根本没有运行,并且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()">我可以让代码运行(由Daniel Beck提供)。尽管如此,我的代码找不到段落标记。

3 个答案:

答案 0 :(得分:0)

你有一些问题,但最大的问题是

  • 您对setTimeout的调用立即调用了这些函数 因为你使用括号来传递参数,但是那样 调用该函数。 setTimeout需要功能参考
  • 您的.querySelector无法找到该元素 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>

答案 1 :(得分:0)

你有三个问题:

  • rulesSlideshow()函数分配给onload,但实际上从未调用。您可以通过在function() { ... }()的函数末尾添加括号来创建 Immediately Invoked Function Expression (IIFE) 来实现此目的。

  • 您的选择器querySelector("rules")实际上不会定位任何内容;您需要指定.前缀为.querySelector(".rules")的类。

  • 您将所有超时设置为4000。因为它们会以异步运行,所以它们都会在同时时触发。因此,您只能看到最终输出(e)。要真正“抵消”输出,您需要将中的超时设置为,或者使用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>

另请注意,您无需在rulesShowshow()内自行调用rulesSlideshow();这已从上面的代码段中删除。

答案 2 :(得分:0)

定义onload处理程序

如果您尝试通过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="...">这样的内联事件属性,而是在代码中定义这些处理程序 - 但这两种技术都是仍然能很好地运作。)

querySelector

由于您正在寻找一个类名,您需要包含&#34;。&#34;:

document.querySelector(".rules").innerHTML = rule;

超时

由于所有超时都具有相同的时间值,因此它们会同时运行(或足够接近) - 因此您只能看到最后一个的结果。如果您希望每次通话之间有四秒钟的间隔,则需要不同的超时值。

此外,由于rulesSlideshow在运行后立即调用自身,因此最终会出现堆栈溢出。这也需要一个setTimeout(尽管你正在做的是定期重复这个功能,用setInterval调用它可能更合适。)

在setTimeout

中的功能

setTimeout期望接收一个函数,但是你将调用函数的结果传递给它。如果你在setRule上不需要参数,你可以使用这个简写:

setTimeout(setRule, 4000)

但是使用param,你需要一个匿名的包装器:

setTimeout(function() {setRule("x")}, 4000)

演示

将所有内容放在一起(我已将它从onload切换到onclick,因为onload很难在堆栈片段中展示,但其余部分是相同的):

&#13;
&#13;
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;
}
&#13;
(Click anywhere to start)
<p id="rule" class="rules"></p>
&#13;
&#13;
&#13;