【问题标题】:Can't understand Javascript eventhandler with for loop code无法理解带有 for 循环代码的 Javascript 事件处理程序
【发布时间】:2015-02-06 23:09:16
【问题描述】:

我正在尝试学习 JavaScript,我看到了一个代码,可以根据您按下的按钮更改网页的 css 样式。

我无法理解 for 循环为何或如何指示女巫按钮被按下。这是javascript部分:

var buttons = document.getElementsByTagName("button");

var len = buttons.length;

for (i = 0; i < len; i++) {
  buttons[i].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };
}

http://jsfiddle.net/qp9jwwq6/

我查看了网络和 w3 学校,但他们没有用 for 循环解释该代码。谁能给我解释一下?

谢谢

【问题讨论】:

  • 将点击监听器添加到每个将正文类设置为按钮文本的&lt;button&gt;

标签: javascript html eventhandler


【解决方案1】:

让我们分解一下。

首先,我们需要访问页面上的 DOM 元素,因此我们通过使用 document 本身的方法来实现,该方法将返回我们想要操作的元素。

var buttons = document.getElementsByTagName("button");

buttons 变量将是页面上所有按钮的列表。我们想对所有这些做一些事情,所以首先我们缓存列表的长度,即计算我们有多少个按钮。

var len = buttons.length;

然后我们基本上说:将 i 设置为 0,然后将其递增 1 直到等于我们拥有的按钮数。

for (i = 0; i < len; i++) {

现在,要访问列表中的一个按钮,我们需要使用括号表示法。所以buttons[0] 是第一个元素,buttons[1] 是第二个元素,依此类推。由于i 从0 开始,我们将i 放在括号中,以便在每次迭代时它都会访问列表中的下一个按钮。

  buttons[i].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };
}

这相当于做:

 buttons[0].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

 buttons[1].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

 buttons[2].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

// etc.

当然那是超级低效的,而且我们可能不知道页面有多少个按钮。所以我们把所有的按钮都放在那里,找出有多少,然后遍历每个按钮并为它分配一个事件处理程序以及一个新类。

现在,查看 onclick 处理程序本身,我们可以看到它首先在被单击的按钮中找到 HTML,将其转换为小写字母,并将其分配给一个变量:

var className = this.innerHTML.toLowerCase();

通过使用this,我们确保每个按钮在被点击时都知道获得它自己的innerHTML。我们不会跟踪哪个按钮是哪个,我们只是告诉每个按钮检查它自己的内容。

然后它所做的就是将body HTML 元素的类更改为我们刚刚解析的任何内容

document.body.className = className;

所以说你有类似的东西

<button>success</button>
<button>failure</button>
<button>warning</button>

单击第一个按钮会将&lt;body&gt; 元素的类设置为success,单击第二个按钮会将其设置为failure,第三个按钮会将其设置为warning

【讨论】:

    【解决方案2】:

    第一行将所有按钮保存在一个名为按钮的变量中。这实际上是一个数组,因为页面上可以有多个按钮。然后您遍历每个按钮并定义一个应在单击时执行的函数。假设您有 2 个按钮,那么按钮 [0] 和按钮 [1] 将获得该功能。

    【讨论】:

      【解决方案3】:

      首先,一般来说,这段代码的底层基础有点不稳定、不寻常和不稳健,所以不要指望你即将学习任何关于 JavaScript 或代码设计的强大洞察力。

      关于答案:

      for 循环不会“指示”按下了哪个按钮。相反,它遍历页面上的每个按钮元素,并将 exact same 函数定义分配给每个元素的 onclick 属性。单击特定按钮元素时最终运行的代码(这里我说的是函数体)通过分配给body 元素将CSS 类分配给document.body.className

      您的问题是询问函数如何知道将哪个类名分配给document.body.className。该函数从按钮元素的innerHTML 中获取类名,可以作为this.innerHTML 访问(因为在事件处理程序中,this 是对发生触发事件的元素的引用)。 HTML &lt;button&gt; 元素有点特别,虽然它通常是一个看起来很简单的按钮,但它也是一个非叶节点,这意味着它包含自己的 HTML。你可以在里面放很多东西,但是在这个例子中,它们只有一个纯文本节点,它由完全(或几乎完全)类名组成(Normal 用于一个,Changed 用于另一个)。这就是函数如何获取特定于该按钮的 CSS 类名的方式;它从被点击的&lt;button&gt; 元素内的文本中抓取它。

      我在后面说“几乎完全一样”,因为按钮文本和它们在 CSS 规则中定义的实际 CSS 类(它们是 normalchanged)之间实际上存在字母大小写差异。这就是为什么他们必须在分配类名之前降低提取的按钮文本 (toLowerCase()) 的字母大小写。 CSS 类区分大小写(请参阅Are CSS selectors case-sensitive?)。

      正如我所说,这是不寻常的代码。在纯 HTML 文本和代码元数据(本例中为 CSS 类)之间创建映射(尤其是不精确的映射!)是相当不明智的。

      【讨论】:

        猜你喜欢
        • 2011-09-09
        • 1970-01-01
        • 2012-10-12
        • 1970-01-01
        • 2015-04-05
        • 2018-08-14
        • 1970-01-01
        • 2013-10-15
        • 2018-05-02
        相关资源
        最近更新 更多