如何在JavaScript中迭代表格行和单元格?

247
如果我有一个HTML表格...怎么办
<div id="myTabDiv">
<table name="mytab" id="mytab1">
  <tr> 
    <td>col1 Val1</td>
    <td>col2 Val2</td>
  </tr>
  <tr>
    <td>col1 Val3</td>
    <td>col2 Val4</td>
  </tr>
</table>
</div>

如果我想要迭代遍历所有表格行(假设每次检查时行数可能会改变)并从JavaScript内部检索每行中每个单元格的值,我该如何操作?

15个回答

386

如果你想要遍历每一行(<tr>),并且知道/识别每一行(<tr>),然后迭代遍历每一行(<tr>)的每一列(<td>),那么这就是正确的方法。

var table = document.getElementById("mytab1");
for (var i = 0, row; row = table.rows[i]; i++) {
   //iterate through rows
   //rows would be accessed using the "row" variable assigned in the for loop
   for (var j = 0, col; col = row.cells[j]; j++) {
     //iterate through columns
     //columns would be accessed using the "col" variable assigned in the for loop
   }  
}

如果你只想遍历单元格(<td>),而不关心所在的行,则可以使用以下方法。

var table = document.getElementById("mytab1");
for (var i = 0, cell; cell = table.cells[i]; i++) {
     //iterate through cells
     //cells would be accessed using the "cell" variable assigned in the for loop
}

7
ex2,table.cells 不兼容浏览器。 - EricG
10
我在将近4年前发布了这个答案...那时连IE 9都还没有被提出来的想法! - John Hartsock
@JohnHartsock 我知道,但我使用了你的解决方案并发现它在IE上不起作用。这只是一个评论,提醒其他人...无论如何,我还是投了你的答案赞;-) - William Remacle
function itTable() { document.writeln("itTable"); var table = document.getElementById("mytab"); for (var i = 0, row; row = table.rows[i]; i++) { document.writeln(i); for (var j = 0, col; col = row.cells[j]; j++) { document.writeln(j); }
} document.writeln("end-itTable"); } 为什么这段代码无法像上面的表格一样循环遍历表格?
- Doug Hauf
对于那些(通过谷歌搜索)需要一个简单且小巧table.cells shim(用于修补一些旧的/面向IE的代码),请参见我的答案以回答问题:Firefox浏览器不识别table.cells吗? - GitaarLAB
显示剩余3条评论

79

你可以考虑使用jQuery。使用jQuery可以轻松完成此操作,可能看起来像这样:

$('#mytab1 tr').each(function(){
    $(this).find('td').each(function(){
        //do your stuff, you can use $(this) to get current cell
    })
})

3
无法使用 jQuery...公司不允许。不要问为什么。 - GregH
25
那是个疯狂的政策。你可以从jQuery中复制粘贴所需的相关函数到自己的应用程序代码中,这样做不会违反使用他人在线代码的政策,否则你也不会在这里了。 - Clinton
19
@Judy:不同意“疯狂政策”……有很多理由不使用jQuery。 - Bigjim
5
禁止使用JQuery的另一个原因是对于嵌入式网站来说,比如我正在使用一个只有250Kb的嵌入式WiFi芯片作为整个网站。由于所有图片都在那里,所以这已经很挤了。 - Nick
2
当你只需要2-3个函数时,jQuery是无用的。在与PHP编码时,它会变得缓慢和混乱。 - TomeeNS
显示剩余2条评论

39
尝试
for (let row of mytab1.rows) 
{
    for(let cell of row.cells) 
    {
       let val = cell.innerText; // your code below
    }
}

for (let row of mytab1.rows) 
{
    for(let cell of row.cells) 
    {
       console.log(cell.innerText)
    }
}
<div id="myTabDiv">
<table name="mytab" id="mytab1">
  <tr> 
    <td>col1 Val1</td>
    <td>col2 Val2</td>
  </tr>
  <tr>
    <td>col1 Val3</td>
    <td>col2 Val4</td>
  </tr>
</table>
</div>

for ( let [i,row] of [...mytab1.rows].entries() ) 
{
    for( let [j,cell] of [...row.cells].entries() ) 
    {
       console.log(`[${i},${j}] = ${cell.innerText}`)
    }
}
<div id="myTabDiv">
<table name="mytab" id="mytab1">
  <tr> 
    <td>col1 Val1</td>
    <td>col2 Val2</td>
  </tr>
  <tr>
    <td>col1 Val3</td>
    <td>col2 Val4</td>
  </tr>
</table>
</div>


3
干净,我想说。 - Shobi
1
请注意循环中的 "for ... of"。在您的答案中加入一些解释会更好。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of - pensum
1
简单、优雅且功能强大,出色的贡献 - Josue Barrios
优雅的方式在不使用dom/jQuery的情况下完成工作。我该如何最终获取单元格中的所有输入?(或者一行中的所有输入) - ieselisra

17

var table=document.getElementById("mytab1");
var r=0; //start counting rows in table
while(row=table.rows[r++])
{
  var c=0; //start counting columns in row
  while(cell=row.cells[c++])
  {
    cell.innerHTML='[R'+r+'C'+c+']'; // do sth with cell
  }
}
<table id="mytab1">
  <tr>
    <td>A1</td><td>A2</td><td>A3</td>
  </tr>
  <tr>
    <td>B1</td><td>B2</td><td>B3</td>
  </tr>
  <tr>
    <td>C1</td><td>C2</td><td>C3</td>
  </tr>
</table>

在每次while循环中,行/列迭代器都会增加,并将集合中的新行/单元格对象分配给行/单元格变量。当集合中没有更多的行/单元格时,false被分配给行/单元格变量,并且while循环的迭代停止(退出)。


在之前的帖子中: while (cell=row[r].cells[c++] 应该是 row.cells[c++],其中 row 是当前对象,sth 代码的示例为:mycoldata = cell.innerHTML. - fib Littul

12
更好的解决方案:使用JavaScript的原生Array.from()方法将HTMLCollection对象转换为数组,然后您可以使用标准的数组函数。
var t = document.getElementById('mytab1');
if(t) {
    Array.from(t.rows || []).forEach((tr, row_ind) => {
        Array.from(tr.cells || []).forEach((cell, col_ind) => {
            console.log('Value at row/col [' + row_ind + ',' + col_ind + '] = ' + cell.textContent);
        });
    });
}

你也可以使用tr.rowIndexcell.colIndex来代替使用row_indcol_ind
我更喜欢这种方法,而不是前两个最高票答案,因为它不会用全局变量ijrowcol来混乱你的代码,因此它提供了干净、模块化的代码,不会产生任何副作用(或引发lint/编译器警告)...而且不需要其他库(如jquery)。此外,它还可以让你的代码访问elementindex变量,而不仅仅是元素,如果你喜欢隐藏索引,你可以在回调参数列表中忽略它。
如果你需要在旧版本(ES2015之前)的Javascript中运行这个代码,可以使用polyfill来填充Array.from

我在Chrome上运行时,在这一行Array.from(tr.cells).forEach((cell, col_ind) => {上遇到了VM150:11 Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))的错误。 - undefined
@Cooper,你的表格可能没有"rows"子元素,或者一些行没有任何单元格吗?如果是这样,我已经更新了示例来处理这种情况。 - undefined

3

以下是使用现代Javascript ES6+的一种解决方案

    const rows = document.querySelector("table")?.rows;
    if (!rows) {
      return;
    }
    Array.from(rows).forEach(row => {
      console.log(row);
      const cells = Array.from(row.cells);
      cells.forEach(cell => {
        console.log(cell);
      });
    });
Array.from()方法将HTMLCollection中的行或单元格转换为常规JavaScript数组,可以通过该数组进行迭代。 table.rows使用文档:https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement/rows row.cells使用文档:https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableRowElement

3
如果您想要一个功能风格的样式,就像这样:
    const table = document.getElementById("mytab1");
    const cells = table.rows.toArray()
                  .flatMap(row => row.cells.toArray())
                  .map(cell => cell.innerHTML); //["col1 Val1", "col2 Val2", "col1 Val3", "col2 Val4"]

你可以修改 HTMLCollection 的原型对象(使其类似于 C# 中的扩展方法),并嵌入一个将集合转换为数组的函数,以此来使用上述样式的高阶函数(类似于 C# 中的 linq 样式):

    Object.defineProperty(HTMLCollection.prototype, "toArray", {
        value: function toArray() {
            return Array.prototype.slice.call(this, 0);
        },
        writable: true,
        configurable: true
    });

未捕获的 TypeError: 无法读取未定义的属性 'toArray' --> 这是我尝试这个解决方案时得到的。 - Vineela Thonupunuri
奇怪,我又试了一遍,它正常工作了。虽然我无法重现你指出的错误。也许问题在于浏览器。我使用Edge和IE进行了测试,两者都不起作用。Chrome,Firefox和Safari按预期工作。 - l30.4l3x
我也用Chrome。 - Vineela Thonupunuri
这对我也起作用。显然,Object.defineProperty必须放在其余代码之前,但它可以工作。@Vineela Thonupunuri,你是否尝试按正确的顺序编写代码? - FlippingBinary

2
这个解决方案对我来说完美地解决了问题。
var table = document.getElementById("myTable").rows;
var y;
for(i = 0; i < # of rows; i++)
{    for(j = 0; j < # of columns; j++)
     {
         y = table[i].cells;
         //do something with cells in a row
         y[j].innerHTML = "";
     }
}

这是 JavaScript 吗?因为你的 for 循环看起来有点像 PHP。 - aravk33
2
当你知道该看什么时,许多语言惊人地相似。PHP会在每个变量前使用$,但这里不需要。var也是JavaScript中使用的关键字,而不是PHP,尽管如果他们添加了它,我可能会错过它。-编辑-没有回车换行...正如我所说:逻辑是普遍的。知道如何将其转录为其他语言是一项非常有用的技能,而且并不难学习-我们是具有出色模式匹配能力的智慧生物。识别每种语言之间的差异或简单地使用词法分析器语言定义... - Acecool
如果你正在回答一个问题,“# of rows”并没有说明任何事情... 请使用完整的代码更新你的答案。 - Si8

2

我的解决方案,使用es6:

var table = document.getElementById('mytab1');

var data = [...table.rows].map(row => [...row.cells].map(td => td.innerText));

console.log(data)

参考文献:
https://developer.mozilla.org/pt-BR/docs/Web/API/HTMLCollection

该链接提供了有关HTMLCollection的详细信息,HTMLCollection是一个包含HTML元素的列表,可以使用JavaScript访问和操作它们。

2
你可以使用.querySelectorAll()选择所有td元素,然后使用.forEach()循环遍历它们。可以通过.innerHTML获取它们的值。"最初的回答"。

const cells = document.querySelectorAll('td');
cells.forEach(function(cell) {
  console.log(cell.innerHTML);
})
<table name="mytab" id="mytab1">
  <tr> 
    <td>col1 Val1</td>
    <td>col2 Val2</td>
  </tr>
  <tr>
    <td>col1 Val3</td>
    <td>col2 Val4</td>
  </tr>
</table>

如果您只想从特定行选择列,请使用伪类 :nth-child() 来选择特定的 tr,可以选择结合使用子级组合器(>) (如果您有一个表格在另一个表格中会很有用):原始答案为 "最初的回答"。

const cells = document.querySelectorAll('tr:nth-child(2) > td');
cells.forEach(function(cell) {
  console.log(cell.innerHTML);
})
<table name="mytab" id="mytab1">
  <tr> 
    <td>col1 Val1</td>
    <td>col2 Val2</td>
  </tr>
  <tr>
    <td>col1 Val3</td>
    <td>col2 Val4</td>
  </tr>
</table>


最简单的修改所有单元格的方法。我用它来删除单元格样式。 - Shnigi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接