专栏首页京程一灯如何用原生 DOM API 生成表格 [每日前端夜话0x35]

如何用原生 DOM API 生成表格 [每日前端夜话0x35]

每日前端夜话0x35

每日前端夜话,陪你聊前端。

每天晚上18:00准时推送。

正文共:6428 字 1 图

预计阅读时间: 17 分钟

翻译:疯狂的技术宅 原文:https://www.valentinog.com/blog/html-table/

怎样用原生 JavaScript 生成表格需?本文告诉你答案!

回到基础:如何用原生 DOM API 生成表格

这是一个刷 JavaScript 经验值的好机会:在技术面试中出现的最多的一个问题就是**怎样用原生 API 操作 DOM **。

在下面的教程中,我们将了解如何使用 JavaScript 生成表格,而无需依赖任何库或框架。

你将学到些什么

在本教程中,你将学习如何:

  • 用 JavaScript 生成一个表格
  • 用本机 DOM API 来操作表

要求

要学习本教程,你应该对 HTML 和 JavaScript 有基本的了解。

需求

Eloquent JavaScript 是一本非常好的 JavaScript 书籍。这本书很简洁,也不乏味,同时有大量的练习。以下练习改编自第 14 章,它被称为“构建表格”。

题目要求你用 JavaScript 构建一个 HTML 表。你的任务是依据 “mountains” 数组中的数据生成表格,将对象中的key对应到列并且每行一个对象

每个对象都是如下形式:

1{ name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" }

我们有一个名称,一个高度和一个山峰所在的位置。但 HTML 表格是什么? HTML 表格是包含表格数据的元素,以行和列的形式显示。这意味着给出以下数组:

1let mountains = [
2  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
3  { name: "Monte Falterona", height: 1654, place: "Parco Foreste Casentinesi" }
4];

我们打算生成下表:

 1<table>
 2    <thead>
 3    <tr>
 4        <th>name</th>
 5        <th>height</th>
 6        <th>place</th>
 7    </tr>
 8    </thead>
 9    <tbody>
10    <tr>
11        <td>Monte Falco</td>
12        <td>1658</td>
13        <td>Parco Foreste Casentinesi</td>
14    </tr>
15    <tr>
16        <td>Monte Falterona</td>
17        <td>1654</td>
18        <td>Parco Foreste Casentinesi</td>
19    </tr>
20    </tbody>
21</table>

如你所见,该表有一个 thead(表头),其中包含一个具有三个th(表格标题)的 **tr(表格行) **。

然后是tbody(表体) 中包含一堆 tr(表格行)。每个表格行包含一定数量的 td元素(表格单元格)

有了这些要求,就可以开始编写 JavaScript 文件了。我们的起点可以是以下 HTML:

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4    <meta charset="UTF-8">
 5    <title>Build a table</title>
 6</head>
 7<body>
 8<table>
 9<!-- here goes our data! -->
10</table>
11</body>
12<script src="build-table.js"></script>
13</html>

将文件另存为 **build-table.html ** 并继续下一部分。

生成表头

在与 build-table.html 相同的文件夹中创建一个名为 build-table.js 的新文件,并在文件定义数组:

1let mountains = [
2  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
3  { name: "Monte Falterona", height: 1654, place: "Parco Foreste Casentinesi" },
4  { name: "Poggio Scali", height: 1520, place: "Parco Foreste Casentinesi" },
5  { name: "Pratomagno", height: 1592, place: "Parco Foreste Casentinesi" },
6  { name: "Monte Amiata", height: 1738, place: "Siena" }
7];

第一个目标是生成表头。我们知道本机方法 createElement() 会创建传递给它的任何元素。假设我们要创建一个表头,可以用 document.createElement(‘thead’)。不过还有更好的办法吗?

让我们先到 MDN 上查阅一下 element table reference 【https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table】。你可以看到表格的DOM接口是 HTMLTableElement

HTMLTableElement 的有趣之处在于它公开的方法中有 createTHead()。没错!createTHead 返回与给定表关联的表头元素,更 6 的是,如果表中不存在头的话,createTHead 会帮我们创建一个。

有了这些知识,接下来在我们的文件中创建一个函数,将 table 作为参数。鉴于我们的需求,可以在其中创建一个新的 thead

1function generateTableHead(table) {
2  let thead = table.createTHead();
3}

现在找到我们的表格(记住在 build-table.html 中有一个)并将其传给我们的函数:

1function generateTableHead(table) {
2  let thead = table.createTHead();
3}
4
5let table = document.querySelector("table");
6generateTableHead(table);

如果你在浏览器中打开 build-table.html,在屏幕上还看不到任何内容,不过可以在开发者工具中看到处理的结果。填充表头的工作只做了一半,可以看到表头中填充了一堆 th。每个表头必须映射到对象描述数据组成的 key 上。

信息已经存在于数组 mountains 中的第一个对象内部。可以迭代第一个对象的 key:

1let mountains = [
2  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
3    //
4];

然后用得到的 key 生成三个表头。但是要先在 thead 中添加一行!这时候该用 document.createElement(“TR”) 了吧?不不不。HTMLTableRowElement 提供了一个 insertRow() 方法,可以在表头上调用。让我们重构一下 generateTableHead 函数:

1function generateTableHead(table) {
2  let thead = table.createTHead();
3  let row = thead.insertRow();
4}

新行应包含三个 th(表头),需要手动创建,对于每个 th 元素,我们将附加一个文本节点。这个函数可以使用另一个参数来进行迭代:

 1function generateTableHead(table, data) {
 2  let thead = table.createTHead();
 3  let row = thead.insertRow();
 4  for (let key of data) {
 5    let th = document.createElement("th");
 6    let text = document.createTextNode(key);
 7    th.appendChild(text);
 8    row.appendChild(th);
 9  }
10}
11
12let table = document.querySelector("table");
13let data = Object.keys(mountains[0]);
14generateTableHead(table, data);

保存文件并刷新 build-table.html:你应该看到你的表头中被填充了 name、height 和 place。 有时用 React 和 Vue 偷懒的感觉真好,直接操作 DOM 是多么艰难和繁琐。不过我们的工作还没有完成。

接下来该填表了……

生成行和单元格

为了填充表格可以遵循同样的方法,但这次我们需要迭代 mountains 数组中的每个对象。当进入 for…of 循环时,将为每个项目创建一个新行

要创建行,你将用到 insertRow()

但我们不能止步于此。在主循环内部,需要一个内循环,这次要用到 **for… in **。内部循环迭代当前对象的每个 key,同时它:

  • 创建一个新单元格
  • 创建一个新的文本节点
  • 将文本节点附加到单元格

使用 HTMLTableRowElement 【https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableRowElement】的另一个方法 insertCell() 创建单元格。

也就是说通过以上逻辑可以填充我们的表。打开 build-table.js 并创建一个名为 generateTable 的新函数。命名可以与我们现有的函数相同:

 1function generateTable(table, data) {
 2  for (let element of data) {
 3    let row = table.insertRow();
 4    for (key in element) {
 5      let cell = row.insertCell();
 6      let text = document.createTextNode(element[key]);
 7      cell.appendChild(text);
 8    }
 9  }
10}

可以这样调用它:

1generateTable(table, mountains);

最后来看看完整的代码:

 1let mountains = [
 2  { name: "Monte Falco", height: 1658, place: "Parco Foreste Casentinesi" },
 3  { name: "Monte Falterona", height: 1654, place: "Parco Foreste Casentinesi" },
 4  { name: "Poggio Scali", height: 1520, place: "Parco Foreste Casentinesi" },
 5  { name: "Pratomagno", height: 1592, place: "Parco Foreste Casentinesi" },
 6  { name: "Monte Amiata", height: 1738, place: "Siena" }
 7];
 8
 9function generateTableHead(table, data) {
10  let thead = table.createTHead();
11  let row = thead.insertRow();
12  for (let key of data) {
13    let th = document.createElement("th");
14    let text = document.createTextNode(key);
15    th.appendChild(text);
16    row.appendChild(th);
17  }
18}
19
20function generateTable(table, data) {
21  for (let element of data) {
22    let row = table.insertRow();
23    for (key in element) {
24      let cell = row.insertCell();
25      let text = document.createTextNode(element[key]);
26      cell.appendChild(text);
27    }
28  }
29}
30
31let table = document.querySelector("table");
32let data = Object.keys(mountains[0]);
33generateTableHead(table, data);
34generateTable(table, mountains);

你觉得它能工作吗?让我们来试试看:

生成行和单元格

呃……看起来行被附加到了表头而不是表体。另外没有table body

但是如果切换函数调用顺序会怎么样呢?试试吧:

1// omitted for brevity
2
3let table = document.querySelector("table");
4let data = Object.keys(mountains[0]);
5generateTable(table, mountains); // generate the table first
6generateTableHead(table, data); // then the head

再次刷新浏览器:

生成行和单元格,插入行

好使!另外还得到了一个 tbody。为什么会这样?当你在空表上调用 insertRow() 时,这些方法会为自动你创建一个tbody(如果没有的话)。

做得好!不过我们的代码可能没进行很好的组织(有太多的全局绑定),这些将会在下一篇文章中提到。

到此为止,你应该能够在不依赖任何外部库的情况下操作HTML表了。恭喜!

总结

在本教程中,我们学到了如何用原生 JavaScript 生成表格。 HTML 表格在DOM中由 HTMLTableElement 体现。这个接口公开了很多有用的方法,其中 createTHead 用于操作表头,insertRow 用来插入行。

另外 HTML 表格的行继承自 HTMLTableRowElement。这个接口有两种方法,其中最重要的是 insertCell

给定一个对象数组,可以使用 for…of 循环来迭代生成行。对于每个对象,我们可以使用 for … in 生成单元格。

我们有一些带有全局绑定的代码(请参阅执行上下文和调用堆栈以获取更多信息)。在下一篇文章中,我们将看到怎样重构这些代码。

jQuery正逐渐消失。 Bootstrap将在版本5中删除它【https://github.com/twbs/bootstrap/pull/23586】。 **原生DOM API **越来越好了,替换以前用 jQuery 做的事情是可行的,没有(几乎)任何额外的依赖。

但即使没有 jQuery 也很容易掉进坑里。有人说你不应该在没有 $shinyNewLibrary 的情况下去操纵 DOM。实际上**每个认真的 JavaScript 开发人员都应该知道原生 DOM API,以及如何使用 JavaScript 操作 DOM **。这些问题在技术面试中很容易被问到,你不想因此被拒绝吧?

本教程的代码可在 Github 下载(https://github.com/valentinogagliardi/back-to-js-basics)。

感谢阅读并敬请期待后续!

本文分享自微信公众号 - 京程一灯(jingchengyideng),作者:疯狂的技术宅

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 讲给前端的正则表达式(2):写出更优雅、更精确的正则表达式[每日前端夜话0x101]

    今天,我们回到 JavaScript 中的正则表达式。如果你还是新手,请查看上一篇文章。这次,我们将学习如何编写更优雅的模式并定义搜索字符串的位置。

    疯狂的技术宅
  • 11个最好的JavaScript动态效果库[每日前端夜话0x3E]

    当我想要在网上找一个简洁的 Javascript 动效库时,总是发现很多“推荐”的库都是缺乏持续维护的。

    疯狂的技术宅
  • 提交到不同URL的表单按钮

    这是几天前想到的,我忘了在哪,但是我把它记在了我的小笔记本上,打算发到博客里。我把它写下来是因为我听到一些把它过于复杂化的东西。

    疯狂的技术宅
  • 响铃:百度Q2财报再创新高,恰是踩对了内容赛道的拐点

    又涨了!近日百度2018Q2财报发布,营收额达260亿元人民币,在Q1总营收209亿元的基础上继续增长。而这亮眼的成绩离不开其核心业务“搜索+信息流“所做出的贡...

    曾响铃
  • 003.Kubernetes二进制部署准备

    其他更多前置准备见:https://kubernetes.io/zh/docs/setup/independent/install-kubeadm/

    木二
  • Python中几个有趣的函数

    众所周知,python功能强大、语法灵活,这些得益于其丰富而强大的库。除了众多第三方库和方法函数,python自带的很多函数也非常有趣,用起来称得上优雅。

    luanhz
  • 如何用好抓包工具wireshark?装好插件最为重要!

    Wireshark是一款开源的抓包软件,同时该软件能够显示很多常见的通用协议,是因为内置了常见协议的解析器。

    网络技术联盟站
  • hdu--DFS

    DFS Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/...

    Gxjun
  • SAP Hybris Commerce里类似ABAP里的透明表设计

    标题的“透明表”得上引号,原因是因为Hybris里的table modelling和Netweaver里的transparent table还不是绝对的一致, ...

    Jerry Wang
  • Hadoop入门

    阿dai学长

扫码关注云+社区

领取腾讯云代金券