使用JavaScript创建表的这些方法有哪些优缺点?

时间:2022-06-08 22:54:33

I found two ways to create a table in JS:

我找到了两种在JS中创建表的方法:

  1. Using insertRow and insertCell:

    使用insertRow和insertCell:

    var table = document.getElementById ("table");
    var row = table.insertRow (1);
    var cell = row.insertCell (0);
    cell.innerHTML = "New row";
    
  2. Using plain DOM operations:

    使用纯DOM操作:

    var tbl     = document.createElement("table");
    var tblBody = document.createElement("tbody");
    
    // creating all cells
    for (var j = 0; j < 2; j++) {
      // creates a table row
      var row = document.createElement("tr");
    
      for (var i = 0; i < 2; i++) {
        // Create a <td> element and a text node, make the text
        // node the contents of the <td>, and put the <td> at
        // the end of the table row
        var cell = document.createElement("td");
        var cellText = document.createTextNode("cell is row "+j+", column "+i);
        cell.appendChild(cellText);
        row.appendChild(cell);
      }
    
      // add the row to the end of the table body
      tblBody.appendChild(row);
    }
    

The first as I see is specially created for the table, but the second is mentioned on MDN, so I'm a bit confused what methods to use. What are the advantages and disadvantages of each? When is one used over another?

我看到的第一个是专门为表创建的,但第二个是在MDN上提到的,所以我有点困惑使用什么方法。各有哪些优缺点?何时使用另一个?

3 个解决方案

#1


4  

If you can avoid using the elements, and just put a string into an innerHTML you'll get the best performance. Here are some different ways to create a table.

如果您可以避免使用元素,只需将字符串放入innerHTML中,您将获得最佳性能。以下是创建表的一些不同方法。

Functional Code demo

We can create some functions to generate our HTML. This code will be very fast (but could be faster). We'll assume this data for all of these examples.

我们可以创建一些函数来生成我们的HTML。这段代码会非常快(但可能会更快)。我们将假设所有这些示例的数据。

var heading = ['Name', 'Points'];

var data = [
  ["Joe", 50],
  ["Jack", 80],
  ["Doug <b>'the hammer'</b> Jones", 76]
];

We can then generate our table like so,

然后我们可以像这样生成我们的表,

document.body.innerHTML = table(heading, data);
function wrapTag(tag, html) {
  return "<" + tag + ">" + html + "</" + tag + ">";
}


function table(head, body) {
    return wrapTag("table", thead(head)
    + tbody(body));
}

function thead(head) {
  var _th = head.map(wrapTag.bind(null, "th"));
  var _tr = wrapTag("tr", _th.join("\n"));
  return wrapTag("thead", _tr);
}

function tbody(body) {
  return body.map(tr).join("\n");
}

function tr(row) {
  var _td = row.map(wrapTag.bind(null, "td"));
  return wrapTag("tr", _td.join("\n"));
}

KnockoutJS demo

In Knockout we can give it an object, and have it map directly to our HTML. With the heading and data variables defined above, we map this like so.

在Knockout中,我们可以给它一个对象,并让它直接映射到我们的HTML。使用上面定义的标题和数据变量,我们就像这样映射。

ko.applyBindings({heading: heading, data: data});

Our HTML makes use of the foreach binding, which iterates over an array. $data refers to the current array item.

我们的HTML使用foreach绑定,它遍历数组。 $ data是指当前数组项。

<table>
  <thead>
    <tr data-bind="foreach: heading">
      <th data-bind="text: $data"></th>
    </tr>
  </thead>
  <tbody data-bind="foreach: data">
    <tr data-bind="foreach: $data">
      <td data-bind="html: $data"></td>
    </tr>
  </tbody>
</table>

AngularJS demo

Using the same data from above, we can create an AngularJS controller.

使用上面的相同数据,我们可以创建一个AngularJS控制器。

function MyTableCtrl($scope) {
  $scope.heading = heading;
  $scope.data = data;
}

Our HTML is similar to KnockoutJS. One difference is the looping syntax, which lets us name our elements, e.g., row in data, instead of referring to elements as $data.

我们的HTML类似于KnockoutJS。一个区别是循环语法,它允许我们命名我们的元素,例如,数据中的行,而不是将元素称为$ data。

  <table ng-controller="MyTableCtrl">
    <thead>
      <tr>
        <th ng-repeat="head in heading">{{head}}</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="row in data">
        <td ng-repeat="content in row" ng-bind-html-unsafe="content"></td>
      </tr>
    </tbody>
  </table>

documentFragment demo

credit to @Ian

归功于@Ian

This is faster than regular DOM manipulation, and provides a nicer syntax than combining strings.

这比常规DOM操作更快,并且提供比组合字符串更好的语法。

newTable = createTable(heading, data);
document.body.appendChild(newTable);
function createTable(h, c) {
    var frag, table, head, body;

    frag = document.createDocumentFragment();
    table = document.createElement("table");
    head = createHeader(h);
    body = createContent(c);

    table.appendChild(head);
    table.appendChild(body);

    frag.appendChild(table);

    return frag.cloneNode(true);
}

function createHeader(data) {
    var thead, rowEl, col, colEl, text, i, j;

    thead = document.createElement("thead")
    rowEl = document.createElement("tr");

    for (i = 0, j = data.length; i < j; i++) {
        col = data[i];
        colEl = document.createElement("td");
        text = document.createTextNode(col);
        colEl.appendChild(text);
        rowEl.appendChild(colEl);
    }

    thead.appendChild(rowEl);

    return thead;
}

function createContent(data) {
    var content, row, rowEl, col, colEl, text, i, j, k, l;

    content = document.createElement("tbody");

    for (i = 0, j = data.length; i < j; i++) {
        row = data[i];
        rowEl = document.createElement("tr");
        for (k = 0, l = row.length; k < l; k++) {
            col = row[k];
            colEl = document.createElement("td");
            text = document.createTextNode(col);
            colEl.appendChild(text);
            rowEl.appendChild(colEl);
        }
        content.appendChild(rowEl);
    }

    return content;
}

#2


1  

taken from this post: insertRow vs. appendChild

取自这篇文章:insertRow vs. appendChild

insertRow would be the much better. It is supported by grade A browsers and it's less verbose and a cleaner API.

insertRow会好得多。它受到A级浏览器的支持,而且它的冗长和更简洁的API。

insertRow might be argued as more reliable since it's DOM1.

insertRow可能被认为更可靠,因为它是DOM1。

The appendChild method is consistently faster (albeit marginally) across all tested browsers (IE6/7, FF3, Chrome2, Opera9) when operating outside of the DOM, but when trying to modify tables within the document (a more common endeavour) it's significantly slower.

当在DOM之外操作时,appendChild方法在所有测试的浏览器(IE6 / 7,FF3,Chrome2,Opera9)上始终更快(尽管略有差异),但是当尝试修改文档中的表(更常见的尝试)时,它明显变慢。

In other words: definitely use insertRow.

换句话说:绝对使用insertRow。

My personal opinion is: 1 method more clear and uses native methods

我个人的意见是:1方法更清晰,并使用本机方法

#3


0  

I actually use Mustache in day-to-day development, so you can do something like this:

我实际上在日常开发中使用Mustache,所以你可以这样做:

Bare HTML table:

裸HTML表:

<table id="myTable"></table>

Then you can store a template in a non-JS <script> tag. You can assign an id or whatever to retrieve the element.

然后,您可以将模板存储在非JS

<script type="text/template" id="rowTemplate">
  {{#rows}}
  <tr>
    {{#items}}
    <td>
      {{.}}
    </td>
    {{/items}}
  </tr>
  {{/items}}
</script>

Retrieving the template is something like:

检索模板是这样的:

var template = document.getElementById('rowTemplate').innerHTML;

Then you need a data source. Mustache needs an object to do this:

然后你需要一个数据源。 Mustache需要一个对象来执行此操作:

var data = {
  rows : [
    {
      items : ['hello1','world1']
    },{
      items : ['hello2','world2']
    }
  ]
}

Rendering:

var usableHTML = Mustache.render(template,data);

You can then append usableHTML to your table

然后,您可以将usefulHTML附加到表中

document.getElementById('myTable').innerHTML = usableHTML;

#1


4  

If you can avoid using the elements, and just put a string into an innerHTML you'll get the best performance. Here are some different ways to create a table.

如果您可以避免使用元素,只需将字符串放入innerHTML中,您将获得最佳性能。以下是创建表的一些不同方法。

Functional Code demo

We can create some functions to generate our HTML. This code will be very fast (but could be faster). We'll assume this data for all of these examples.

我们可以创建一些函数来生成我们的HTML。这段代码会非常快(但可能会更快)。我们将假设所有这些示例的数据。

var heading = ['Name', 'Points'];

var data = [
  ["Joe", 50],
  ["Jack", 80],
  ["Doug <b>'the hammer'</b> Jones", 76]
];

We can then generate our table like so,

然后我们可以像这样生成我们的表,

document.body.innerHTML = table(heading, data);
function wrapTag(tag, html) {
  return "<" + tag + ">" + html + "</" + tag + ">";
}


function table(head, body) {
    return wrapTag("table", thead(head)
    + tbody(body));
}

function thead(head) {
  var _th = head.map(wrapTag.bind(null, "th"));
  var _tr = wrapTag("tr", _th.join("\n"));
  return wrapTag("thead", _tr);
}

function tbody(body) {
  return body.map(tr).join("\n");
}

function tr(row) {
  var _td = row.map(wrapTag.bind(null, "td"));
  return wrapTag("tr", _td.join("\n"));
}

KnockoutJS demo

In Knockout we can give it an object, and have it map directly to our HTML. With the heading and data variables defined above, we map this like so.

在Knockout中,我们可以给它一个对象,并让它直接映射到我们的HTML。使用上面定义的标题和数据变量,我们就像这样映射。

ko.applyBindings({heading: heading, data: data});

Our HTML makes use of the foreach binding, which iterates over an array. $data refers to the current array item.

我们的HTML使用foreach绑定,它遍历数组。 $ data是指当前数组项。

<table>
  <thead>
    <tr data-bind="foreach: heading">
      <th data-bind="text: $data"></th>
    </tr>
  </thead>
  <tbody data-bind="foreach: data">
    <tr data-bind="foreach: $data">
      <td data-bind="html: $data"></td>
    </tr>
  </tbody>
</table>

AngularJS demo

Using the same data from above, we can create an AngularJS controller.

使用上面的相同数据,我们可以创建一个AngularJS控制器。

function MyTableCtrl($scope) {
  $scope.heading = heading;
  $scope.data = data;
}

Our HTML is similar to KnockoutJS. One difference is the looping syntax, which lets us name our elements, e.g., row in data, instead of referring to elements as $data.

我们的HTML类似于KnockoutJS。一个区别是循环语法,它允许我们命名我们的元素,例如,数据中的行,而不是将元素称为$ data。

  <table ng-controller="MyTableCtrl">
    <thead>
      <tr>
        <th ng-repeat="head in heading">{{head}}</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="row in data">
        <td ng-repeat="content in row" ng-bind-html-unsafe="content"></td>
      </tr>
    </tbody>
  </table>

documentFragment demo

credit to @Ian

归功于@Ian

This is faster than regular DOM manipulation, and provides a nicer syntax than combining strings.

这比常规DOM操作更快,并且提供比组合字符串更好的语法。

newTable = createTable(heading, data);
document.body.appendChild(newTable);
function createTable(h, c) {
    var frag, table, head, body;

    frag = document.createDocumentFragment();
    table = document.createElement("table");
    head = createHeader(h);
    body = createContent(c);

    table.appendChild(head);
    table.appendChild(body);

    frag.appendChild(table);

    return frag.cloneNode(true);
}

function createHeader(data) {
    var thead, rowEl, col, colEl, text, i, j;

    thead = document.createElement("thead")
    rowEl = document.createElement("tr");

    for (i = 0, j = data.length; i < j; i++) {
        col = data[i];
        colEl = document.createElement("td");
        text = document.createTextNode(col);
        colEl.appendChild(text);
        rowEl.appendChild(colEl);
    }

    thead.appendChild(rowEl);

    return thead;
}

function createContent(data) {
    var content, row, rowEl, col, colEl, text, i, j, k, l;

    content = document.createElement("tbody");

    for (i = 0, j = data.length; i < j; i++) {
        row = data[i];
        rowEl = document.createElement("tr");
        for (k = 0, l = row.length; k < l; k++) {
            col = row[k];
            colEl = document.createElement("td");
            text = document.createTextNode(col);
            colEl.appendChild(text);
            rowEl.appendChild(colEl);
        }
        content.appendChild(rowEl);
    }

    return content;
}

#2


1  

taken from this post: insertRow vs. appendChild

取自这篇文章:insertRow vs. appendChild

insertRow would be the much better. It is supported by grade A browsers and it's less verbose and a cleaner API.

insertRow会好得多。它受到A级浏览器的支持,而且它的冗长和更简洁的API。

insertRow might be argued as more reliable since it's DOM1.

insertRow可能被认为更可靠,因为它是DOM1。

The appendChild method is consistently faster (albeit marginally) across all tested browsers (IE6/7, FF3, Chrome2, Opera9) when operating outside of the DOM, but when trying to modify tables within the document (a more common endeavour) it's significantly slower.

当在DOM之外操作时,appendChild方法在所有测试的浏览器(IE6 / 7,FF3,Chrome2,Opera9)上始终更快(尽管略有差异),但是当尝试修改文档中的表(更常见的尝试)时,它明显变慢。

In other words: definitely use insertRow.

换句话说:绝对使用insertRow。

My personal opinion is: 1 method more clear and uses native methods

我个人的意见是:1方法更清晰,并使用本机方法

#3


0  

I actually use Mustache in day-to-day development, so you can do something like this:

我实际上在日常开发中使用Mustache,所以你可以这样做:

Bare HTML table:

裸HTML表:

<table id="myTable"></table>

Then you can store a template in a non-JS <script> tag. You can assign an id or whatever to retrieve the element.

然后,您可以将模板存储在非JS

<script type="text/template" id="rowTemplate">
  {{#rows}}
  <tr>
    {{#items}}
    <td>
      {{.}}
    </td>
    {{/items}}
  </tr>
  {{/items}}
</script>

Retrieving the template is something like:

检索模板是这样的:

var template = document.getElementById('rowTemplate').innerHTML;

Then you need a data source. Mustache needs an object to do this:

然后你需要一个数据源。 Mustache需要一个对象来执行此操作:

var data = {
  rows : [
    {
      items : ['hello1','world1']
    },{
      items : ['hello2','world2']
    }
  ]
}

Rendering:

var usableHTML = Mustache.render(template,data);

You can then append usableHTML to your table

然后,您可以将usefulHTML附加到表中

document.getElementById('myTable').innerHTML = usableHTML;