自动将 <th> 的基于数据标签的内容附加到相应的 <td> 以实现响应式 table 视图

Automatically append data-labels based content of <th> to corresponding <td> for responsive table view

我需要根据相应 th 的内容自动将 data-* 标签附加到 td。所以,结果应该是这样的:

<table class="table">
  <thead class="bg-gray-100">
    <tr>
      <th>Heading 1</th>
      <th>Heading 2</th>
      <th>Heading 3</th>
      <th>Heading 4</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td data-label="Heading 1">table cell content</td>
      <td data-label="Heading 2">table cell content</td>
      <td data-label="Heading 3">table cell content</td>
      <td data-label="Heading 4">table cell content</td>
      <td data-label="Heading 5">table cell content</td>
    </tr>
  </tbody>
</table>

虽然有许多 jQuery 解决方案,但我需要用 vanilla JavaScript

来完成

有关代表性 jQuery 解决方案,请参阅: 1.

  1. Pull th content into a td data-label attribute

  2. https://j.eremy.net/responsive-table/)

我很想使用 element.cellIndex 的解决方案,但似乎无法实现。

我做过各种错误的尝试。

这是我最近一次失败的尝试:

function addMobileTableData() {
  var table = document.querySelector('.table');
  var th = table.querySelectorAll('th');
  var td = table.querySelectorAll('td');
  var tdCollection = Array.from(td);
  var thCollection = Array.from(th);
  var thCount = th.length;
  tdCollection.forEach(function(tdItem, index){
    for (index = 0; index < thCount; index++) {
      var headerLabel = thCollection[index].innerHTML;
      console.log(headerLabel);
      tdItem.setAttribute('data-th', headerLabel[index]);
    };
  });
};

这显然是不正确的。它为每个 td 分配一个 data-th 标签,但仅将最后一个字符串中的第一个字符附加到每个 td

如果您赶时间,我们将不胜感激。对我做错了什么的解释会很好。一个完整的工作解决方案是 Fan-Freaking-Tastic。

但是,我会尽我所能。

谢谢。

其实你们很亲近。原来你访问的是你返回的 Header 标签的字符串,因此只返回第一个字符。额外的循环也是不必要的。下面的工作代码片段:

function addMobileTableData() {
  var table = document.querySelector('.table');
  var bodyTrCollection = table.querySelectorAll('tbody tr');
  var th = table.querySelectorAll('th');
  var thCollection = Array.from(th);

  for (var i = 0; i < bodyTrCollection.length; i++) {
    var td = bodyTrCollection[i].querySelectorAll('td');
    var tdCollection = Array.from(td);
    for (var j = 0; j < tdCollection.length; j++) {
      if (j === thCollection.length) {
        continue;
      }
      var headerLabel = thCollection[j].innerHTML;
      tdCollection[j].setAttribute('data-th', headerLabel);
    }
  }
};
addMobileTableData();
<table class="table">
  <thead class="bg-gray-100">
    <tr>
      <th>Heading 1</th>
      <th>Heading 2</th>
      <th>Heading 3</th>
      <th>Heading 4</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
    </tr>
    <tr>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
    </tr>
    <tr>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
      <td>table cell content</td>
    </tr>
  </tbody>
</table>

编辑:添加了一个额外的检查来说明当 th 和 tds 的数量不匹配时的情况。

第二次编辑:函数分解为多行。我现在已经修正了这个错误。

更简洁的版本可以是:

const table = document.querySelector('table.table');
const headerCells = table.querySelectorAll('thead th');

headerCells.forEach((_headerCell, i) => {
  table
    .querySelectorAll(`tbody tr td:nth-child(${i + 1})`)
    .forEach((cell) => {
      cell.dataset.label = headerCells[i].innerText.trim();
    });
});
<table class="table">
  <thead class="bg-gray-100">
    <tr>
      <th>Heading 1</th>
      <th>Heading 2</th>
      <th>Heading 3</th>
      <th>Heading 4</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>cell content</td>
      <td>cell content</td>
      <td>cell content</td>
      <td>cell content</td>
      <td>cell content</td>
    </tr>
  </tbody>
</table>