繁体   English   中英

单击时的Javascript排序表列

[英]Javascript sort table column on click

我的意图是在单击th时按升序对表列(仅单击的列)进行排序。 在进一步单击时,确切的表格列应按降序排列。

到目前为止我得到了什么:
表格正在排序,但单击时所有三列都在排序 - 我只希望对一列进行排序。

 function sortTable(n) { var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0; table = document.getElementById("table"); switching = true; dir = "asc"; while (switching) { switching = false; rows = table.rows; for (i = 1; i < (rows.length - 1); i++) { shouldSwitch = false; x = rows[i].getElementsByTagName("TD")[n]; y = rows[i + 1].getElementsByTagName("TD")[n]; if (dir == "asc") { if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) { shouldSwitch = true; break; } } else if (dir == "desc") { if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) { shouldSwitch = true; break; } } } if (shouldSwitch) { rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); switching = true; switchcount ++; } else { if (switchcount == 0 && dir == "asc") { dir = "desc"; switching = true; } } } }
 <table id="table"> <tr> <th onclick="sortTable(0)">Nummer</th> <th onclick="sortTable(1)">Land</th> <th onclick="sortTable(2)">Name</th> </tr> <tr> <td>2</td> <td>Rumänien</td> <td>Dan</td> </tr> <tr> <td>1</td> <td>Deutschland</td> <td>Aaron</td> </tr> <tr> <td>3</td> <td>USA</td> <td>Peter</td> </tr> </table>

对于描述来说,这看起来也太过分了。 如果您只想对行进行排序,那么该代码是几行:

function compareValues(a, b) {
  // return -1/0/1 based on what you "know" a and b
  // are here. Numbers, text, some custom case-insensitive
  // and natural number ordering, etc. That's up to you.
  // A typical "do whatever JS would do" is:
  return (a<b) ? -1 : (a>b) ? 1 : 0;
}

function sortTable(colnum) {
  // get all the rows in this table:
  let rows = Array.from(table.querySelectorAll(`tr`));

  // but ignore the heading row:
  rows = rows.slice(1);

  // set up the queryselector for getting the indicated
  // column from a row, so we can compare using its value:
  let qs = `td:nth-child(${colnum})`;

  // and then just... sort the rows:
  rows.sort( (r1,r2) => {
    // get each row's relevant column
    let t1 = r1.querySelector(qs);
    let t2 = r2.querySelector(qs);

    // and then effect sorting by comparing their content:
    return compareValues(t1.textContent,t2.textContent);
  });

  // and then the magic part that makes the sorting appear on-page:
  rows.forEach(row => table.appendChild(row));
}

神奇的部分作品,因为DOM节点可以在一个地方只存在,因此,如果您appendChild它的东西,它就会不管它是在第一个地方移动 因此,我们的排序在JS,然后我们运行appendChild在有序,每一行仅仅是从移动“等。无论是”到,该装置后,我们通过每一行运行“孩子列表的末尾” rows , presto:现在根据需要重新排序所有行。

当然,您仍然需要自己编写compareValues(a,b) 我不知道你想在那里做什么,因为也许你想要自然文本比较,或者你想要“如果值是数字,则作为数字进行比较,仅当它们不是作为文本进行比较时”等。

但是您应该做的一件事是不要使用 1998 事件处理。 不要使用onclick ,在 JS 端正确执行此操作。 所以在你的 HTML 中:

<tr>
  <th>Nummer</th>
  <th>Land</th>
  <th>Name</th>
</tr>

然后在 JS 方面:

table.querySelectorAll(`th`).forEach((th, position) => {
  th.addEventListener(`click`, evt => sortTable(position));
});

(更好的是,使用<th><button>Nummer</button></th>并添加基于th button的事件侦听th button ,因为它就是这样。如果您有可以单击以“做某事”的文本,那是一个按钮。使用正确的标记,然后只需使用 CSS 设置您想要的样式,例如无边框、背景:继承等)

也许使用不同的方法。 在渲染之前存储您的数据并对数组进行排序。

 let tblData = [{ number: 2, land: 'Rumänien', name: 'Dan' }, { number: 1, land: 'Deutschland', name: 'Aaron' }, { number: 3, land: 'USA', name: 'Peter' } ]; const getRow = (data) => `<tr><td>${data.number}</td><td>${data.land}</td><td>${data.name}</td></tr>`; const sortNumber = (a, b) => a.number - b.number; const sortLand = (a, b) => (a.land === b.land) ? 0 : (a.land > b.land) ? 1 : -1; const sortName = (a, b) => (a.name === b.name) ? 0 : (a.name > b.name) ? 1 : -1; function buildTable(data) { document.querySelector('tbody').innerHTML = data.map(row => getRow(row)).join(''); } function sortTable(n) { let sort = sortNumber; switch (n) { case 1: sort = sortLand; break; case 2: sort = sortName; } console.log(n); buildTable(tblData.sort(sort)); } buildTable(tblData);
 <table id="table"> <thead> <tr> <th onclick="sortTable(0)">Nummer</th> <th onclick="sortTable(1)">Land</th> <th onclick="sortTable(2)">Name</th> </tr> </thead> <tbody> </tbody> </table>

运行您的代码时,我得到了预期的结果。 我想知道是否仅仅因为您的数据是这样设置的,结果似乎不正确。

例如,您的数据是:

1   Deutschland Aaron
2   Rumänien    Dan
3   USA Peter

对 Number 进行排序,将有 Deutschland First 和 Aaron,并且 Deutschland 和 Aaron 在其余数据之前按字母顺序排在第一位。

因此,其他列正在排序是一种错觉,而实际上它们实际上只是遵循您的数据结构。

Mike 'Pomax' Kamermans的回答效果很好,除了排序表会将<tr>放在<tbody>标记之外,这是不希望的。 这可以通过更改他的答案来轻松解决:

function sortTable(colnum) {
  let tbody = table.querySelector(`tbody`);
  let rows = Array.from(table.querySelectorAll(`tr`));
  
  // other codes...
  
  rows.forEach(row => tbody.appendChild(row));
  table.appendChild(tbody);
}

然后生成的表应该可以正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM