【问题标题】:How to change the visibility of a table row in Javascript?如何在 Javascript 中更改表格行的可见性?
【发布时间】:2016-11-29 18:03:24
【问题描述】:

我正在尝试通过 javascript 显示/隐藏 HTML 表格中的行。选中复选框将显示额外的行,取消选中它将隐藏它们。

<html><body><form><table>
    <tr>
        <td> This row is always visible. </td>
    </tr>
    <tr>
        <td>
            <input id="cbox" type="checkbox" onchange="for(e in document.getElementsByClassName('switchMe')) e.style.display = document.getElementById('cbox').checked ? 'block' : 'none';"/>
            <label for="cbox">Show more …</label>
        </td>
    </tr>
    <tr class="switchMe" style="display: none; ">
        <td> This row will be shown after the user clicks the check box. </td>
    </tr>
    <tr class="switchMe" style="display: none; ">
        <td> This row too. </td>
    </tr>
    <tr>
        <td> This row is always visible. </td>
    </tr>
</table></form></body></html>

但是,什么也没发生,我在控制台中收到 e.style is undefined 错误。如何正确访问&lt;tr&gt; 元素的样式属性?

(我首先尝试将有问题的行放在&lt;div&gt; 中。这不会产生任何错误,但行总是可见的,并且 Firebug 中不存在&lt;div&gt;,因此可能不允许在那里.)

【问题讨论】:

    标签: javascript html-table row visibility


    【解决方案1】:
    • 首先,for..in 非常适合迭代对象,但不适用于 NodeList。
    • 其次,在 html 中设置更改事件侦听器是一种不好的做法。任何人都可以使用开发工具更改标记并操纵系统的行为。你应该使用.addEventListener
    • 第三,定义不带var的变量会使其成为全局变量。

    for..in 的输出

    var el_list = document.querySelectorAll('.switchMe');
    for(var el in el_list){
      console.log(el)
    }
    <form>
      <table>
        <tr>
          <td>This row is always visible.</td>
        </tr>
        <tr>
          <td>
            <input id="cbox" type="checkbox" />
            <label for="cbox">Show more …</label>
          </td>
        </tr>
        <tr class="switchMe" style="display: none; ">
          <td>This row will be shown after the user clicks the check box.</td>
        </tr>
        <tr class="switchMe" style="display: none; ">
          <td>This row too.</td>
        </tr>
        <tr>
          <td>This row is always visible.</td>
        </tr>
      </table>
    </form>

    样本

    JSFiddle

    document.querySelector('#cbox').addEventListener('click', function(e) {
      var switchEl = document.querySelectorAll('.switchMe');
      for (var i = 0; i < switchEl.length; i++)
        switchEl[i].style.display = this.checked ? 'block' : 'none';
    });
    <form>
      <table>
        <tr>
          <td>This row is always visible.</td>
        </tr>
        <tr>
          <td>
            <input id="cbox" type="checkbox" />
            <label for="cbox">Show more …</label>
          </td>
        </tr>
        <tr class="switchMe" style="display: none; ">
          <td>This row will be shown after the user clicks the check box.</td>
        </tr>
        <tr class="switchMe" style="display: none; ">
          <td>This row too.</td>
        </tr>
        <tr>
          <td>This row is always visible.</td>
        </tr>
      </table>
    </form>

    【讨论】:

    • 谢谢。这个对我有用:&lt;input type="checkbox" onchange="var e = document.querySelectorAll('.switchMe'); for (var i = 0; i &lt; e.length; i++) e[i].style.display = this.checked ? 'table-row' : 'none';"/&gt;。为this +1,我不知道这行得通。
    • @Paramaeleon 很高兴为您提供帮助!
    【解决方案2】:

    您在使用 for...in 循环时遇到问题。这不是您应该为数组或(类似数组的)对象选择的真正循环,它们应该只用于遍历对象键和属性,因为它们在数组上非常慢,因为有更快的方法可用。

    for...in 也会修改状态,因此您应该拥有可用的状态,例如。

    const thing = { one: 1, two: 2 }
    for (key in thing) {
      console.log(thing[key])
    }
    

    您从循环内部的外部范围引用 thing

    我认为这是一种更好的方法,因为您在进行迭代时无需处理任何外部状态。

    const rows = Array.from(document.getElementsByClassName('switchMe'))
    const cbox = document.getElementById('cbox')
    
    function changeHandler() {
      rows.forEach(row => {
        row.style.display = cbox.checked ? 'block' : 'none'
      })
    }
    <html>
    
    <body>
      <form>
        <table>
          <tr>
            <td>This row is always visible.</td>
          </tr>
          <tr>
            <td>
              <input id="cbox" type="checkbox" onchange="changeHandler()" />
              <label for="cbox">Show more …</label>
            </td>
          </tr>
          <tr class="switchMe" style="display: none; ">
            <td>This row will be shown after the user clicks the check box.</td>
          </tr>
          <tr class="switchMe" style="display: none; ">
            <td>This row too.</td>
          </tr>
          <tr>
            <td>This row is always visible.</td>
          </tr>
        </table>
      </form>
    </body>
    
    </html>

    【讨论】:

    • 只是一个指针,arrow functionarray.from 是非常强大的工具,但是是 ES6 的一部分,一些旧的浏览器不支持它。使用前请检查它们的兼容性。
    【解决方案3】:

    在不创建其他答案的情况下实现您尝试做的事情的一种方法是如下所示。

    但这并不意味着您应该这样做。在实践中肯定使用显示的其他答案。

    <html>
    
    <body>
      <form>
        <table>
          <tr>
            <td>This row is always visible.</td>
          </tr>
          <tr>
            <td>
              <input id="cbox" type="checkbox" onchange="var arr = document.getElementsByClassName('switchMe'); for(var i = 0; i < arr.length; i++) arr[i].style.display = document.getElementById('cbox').checked ? 'block' : 'none';" />
              <label for="cbox">Show more …</label>
            </td>
          </tr>
          <tr class="switchMe" style="display: none; ">
            <td>This row will be shown after the user clicks the check box.</td>
          </tr>
          <tr class="switchMe" style="display: none; ">
            <td>This row too.</td>
          </tr>
          <tr>
            <td>This row is always visible.</td>
          </tr>
        </table>
      </form>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 2016-07-04
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 2013-04-14
      • 2014-04-07
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多