【问题标题】:How to sort the table and re-generate it with help of pure JavaScript如何在纯 JavaScript 的帮助下对表格进行排序并重新生成它
【发布时间】:2019-08-04 09:49:04
【问题描述】:

我需要按名称对表格进行排序。对于排序,我使用函数

function sortArray(index) {
  let arr = [];
  rows.forEach( elem => {
    arr.push(elem.children[index].textContent); 
  })
  let sort = arr.sort( (a, b) => {
    if ( a > b) {
      return 1;
    }
    if (a < b) {
      return -1;
    }
    return 0;
  });
  console.log(sort);
  return sort;
  }

但我不知道如何重绘表格。我从 JSON 文件动态创建的表。为了开始排序,您需要单击字段名称,然后应该会显示已排序的表格。

const buildHeader = data =>
  Object.keys(data)
    .map(k => `<th>${k}</th>`)
    .join("");
const buildRow = data =>
  Object.keys(data)
    .map(k => `<td>${data[k]}</td>`)
    .join("");
let element = document.querySelector(".people");

function showPeople(people) {
  let table = document.createElement("table");
  table.classList.add("people__table");
  let thead = document.createElement("thead");
  thead.innerHTML = `<tr class="head">${buildHeader(people[0])}</tr>`;
  table.appendChild(thead);
  let tbody = document.createElement("tbody");
  tbody.innerHTML = people
    .map(p => `<tr class="person">${buildRow(p)}</tr>`)
    .join("");
  table.appendChild(tbody);
  element.appendChild(table);
}

const customPeople = data =>
  data.map((p, i) => {
    return {
      name: p.name,
      sex: p.sex,
      born: p.born,
      died: p.died,
      age: p.died - p.born,
      mother: p.mother,
      father: p.father,
    };
  });

showPeople(customPeople(ANCESTRY_FILE));

【问题讨论】:

  • 如果一开始就从JSON动态创建表,可以不对排序后的数据重复这个过程吗?
  • 除此之外:这种方法有效,但 innerHTML 并不是真正必要的。 HTMLTableElement 带有createTHeadinsertRow 等表格创建方法。同样,HTMLTableRow 包含insertCelldeleteCell 等方法。
  • @Lewis 当然可以,但是如何通过点击字段名称来对这些数据进行排序

标签: javascript sorting html-table


【解决方案1】:

类似sortTable 的函数可以完成这项工作:

function sortTable(tbody, index, ascending) {
    Array.prototype.slice.call(tbody.children).sort(
        (tr1, tr2) => tr1.children[index].textContent.localeCompare(tr2.children[index].textContent) * (ascending ? 1 : -1)
        ).forEach(tr => tbody.appendChild(tr));
    }

// demonstration
(function(){
    const thead_tr = document.getElementById('thdtr');
    const tbody = document.getElementById('tbd');
        
    function makeCell() {
        const td = document.createElement('td');
        td.appendChild(document.createTextNode(Math.round(Math.random() * 999999999).toString(36)));
        return td;
        }

    function makeRow() {
        const tr = document.createElement('tr');
        for(let i = 0; i < thead_tr.children.length; i++) tr.appendChild(makeCell());
        return tr;
        }
    
    // adds click-to-sort functionality
    Array.prototype.forEach.call(thead_tr.children, (th, index) => {
        let asc_toggle = false; // false will start off in ascending order
        th.addEventListener('click', event => sortTable(tbody, index, asc_toggle = !asc_toggle));
        });
    
    // fills the table with random alphanumeric data
    for(let i = 0; i < 100; i++) tbody.appendChild(makeRow());
    }());
<table>
    <thead>
        <tr id="thdtr">
            <th>col 1</th>
            <th>col 2</th>
            <th>col 3</th>
        </tr>
    </thead>
    <tbody id="tbd">
    </tbody>
<table>

我的sortTable 函数是一个通用的就地表排序函数,应该适用于任何表。它接受 3 个参数:

  1. tbody - DOMElement - 对 tbody 元素或 table 元素本身的引用,以包含 tr(行)元素的为准。
  2. index - Number - 要排序的列的索引(从 0 开始)。
  3. ascending - Boolean - 顺序是升序 (true) 还是降序 (false)

与当前代码一起使用的示例用法:

sortTable(document.querySelector('.people__table tbody'), 0, true);

【讨论】:

    【解决方案2】:

    请看下面的例子:

    let data = generateData();
    
    let columns = [
      {
        name: "id",
        callback: function() {
          flags.id *= -1;
          doSortInt("id", flags.id);
        }
      },
      {
        name: "name",
        callback: function() {
          flags.name *= -1;
          doSortStrings("name", flags.name);
        }
      },
      {
        name: "age",
        callback: function() {
          flags.age *= -1;
          doSortInt("age", flags.age);
        }
      }
    ];
    
    var flags = {
      id: -1,
      name: -1,
      age: -1
    };
    
    createBasicTable(columns);
    
    populateDataToTable(data);
    
    function doSortInt(prop, flag) {
      data.sort(function(a, b) {
        return flag * (b[prop] - a[prop]);
      });
      populateDataToTable(data);
    }
    
    function doSortStrings(prop, flag) {
      data.sort(function(a, b) {
        return flag * ("" + a[prop]).localeCompare(b[prop]);
      });
      populateDataToTable(data);
    }
    
    /**
     * This function is used to fill in the table with data from array
     */
    function populateDataToTable(data) {
      let tableBody = document.querySelector("#table-body");
      // remove all childs
      while (tableBody.firstChild) {
        tableBody.removeChild(tableBody.firstChild);
      }
    
      // add new data
      data.forEach(function(el) {
        let tr = document.createElement("tr");
    
        let th1 = document.createElement("th");
        th1.innerHTML = el.id;
        tr.appendChild(th1);
    
        let th2 = document.createElement("th");
        th2.innerHTML = el.name;
        tr.appendChild(th2);
    
        let th3 = document.createElement("th");
        th3.innerHTML = el.age;
        tr.appendChild(th3);
    
        tableBody.appendChild(tr);
      });
    }
    
    /**
     * This function is used to create a basic empty table
     */
    function createBasicTable(columns) {
      let element = document.querySelector("#table-container");
      let table = document.createElement("table");
      table.classList.add("people__table");
      let thead = document.createElement("thead");
    
      let tr = document.createElement("tr");
    
      columns.forEach(function(col) {
        let th = document.createElement("th");
        th.classList.add("head");
        th.innerHTML = col.name;
        th.addEventListener("click", col.callback);
        // add listener here
        tr.appendChild(th);
      });
      thead.appendChild(tr);
      table.appendChild(thead);
    
      let tbody = document.createElement("tbody");
      tbody.id = "table-body";
      table.appendChild(tbody);
      element.appendChild(table);
    }
    
    /**
     * This function is used to generate some data for the table
     */
    function generateData() {
      let data = [];
      for (var i = 0; i < 100; i++) {
        let obj = {
          id: i,
          name: "Name_" + (i + 1),
          age: 30 + i * 2
        };
        data.push(obj);
      }
    
      return data;
    }
    <!DOCTYPE html>
    <html class="no-js">
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title></title>
        <meta name="description" content="" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
      </head>
      <body>
    
        <div id="table-container"></div>
      </body>
    </html>

    主要有以下几点:

    在列定义数组中,每个列标题都有回调。然后调用函数

    createBasicTable
    

    创建一个没有数据的空表。并在此函数中注册列标题回调。那么你就有了一个函数

    populateDataToTable
    

    它将一个数组作为参数并使用该数组来构建表格行。 最后,在您的回调中,您只需正确排序数据数组并使用函数更新表格内容:

    populateDataToTable
    

    附言代码不是完美的,但它至少应该给你一个提示,如何实现这个功能。 明天我会尝试改进代码。

    【讨论】:

    • 如果您查看我的回答,您应该能够看到该问题的解决方案一点也不复杂,也不需要对用于生成表格的算法进行彻底检查。
    【解决方案3】:

    您可以将行重新附加到表格主体:

     const body = document querySelector(".people__table > tbody");
    
     for(const el of sort)
       body.appendChild(el);
    

    或者您只是对数据进行排序并重新生成整个表格。

    【讨论】:

    • 当然可以,但是如何通过点击字段名称来对这些数据进行排序。通过使用排序方式启动JSON文件。
    猜你喜欢
    • 2011-11-19
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    相关资源
    最近更新 更多