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

栏目: JavaScript · 发布时间: 5年前

内容简介:翻译:疯狂的技术宅原文:怎样用原生 JavaScript 生成表格需?本文告诉你答案!

翻译:疯狂的技术宅

原文: https://www.valentinog.com/bl...

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

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

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

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

你将学到些什么

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

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

要求

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

需求

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

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

每个对象都是如下形式:

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

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

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

我们打算生成下表:

<table>
    <thead>
    <tr>
        <th>name</th>
        <th>height</th>
        <th>place</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>Monte Falco</td>
        <td>1658</td>
        <td>Parco Foreste Casentinesi</td>
    </tr>
    <tr>
        <td>Monte Falterona</td>
        <td>1654</td>
        <td>Parco Foreste Casentinesi</td>
    </tr>
    </tbody>
</table>

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

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

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Build a table</title>
</head>
<body>
<table>
<!-- here goes our data! -->
</table>
</body>
<script src="build-table.js"></script>
</html>

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

生成表头

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

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

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

让我们先到 MDN 上查阅一下 element table reference 。你可以看到表格的DOM接口是 HTMLTableElement

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

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

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

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

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

let table = document.querySelector("table");
generateTableHead(table);

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

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

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

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

function generateTableHead(table) {
  let thead = table.createTHead();
  let row = thead.insertRow();
}

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

function generateTableHead(table, data) {
  let thead = table.createTHead();
  let row = thead.insertRow();
  for (let key of data) {
    let th = document.createElement("th");
    let text = document.createTextNode(key);
    th.appendChild(text);
    row.appendChild(th);
  }
}

let table = document.querySelector("table");
let data = Object.keys(mountains[0]);
generateTableHead(table, data);

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

接下来该填表了......

生成行和单元格

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

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

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

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

使用 HTMLTableRowElement 的另一个方法 insertCell() 创建单元格。

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

function generateTable(table, data) {
  for (let element of data) {
    let row = table.insertRow();
    for (key in element) {
      let cell = row.insertCell();
      let text = document.createTextNode(element[key]);
      cell.appendChild(text);
    }
  }
}

可以这样调用它:

generateTable(table, mountains);

最后来看看完整的代码:

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

function generateTableHead(table, data) {
  let thead = table.createTHead();
  let row = thead.insertRow();
  for (let key of data) {
    let th = document.createElement("th");
    let text = document.createTextNode(key);
    th.appendChild(text);
    row.appendChild(th);
  }
}

function generateTable(table, data) {
  for (let element of data) {
    let row = table.insertRow();
    for (key in element) {
      let cell = row.insertCell();
      let text = document.createTextNode(element[key]);
      cell.appendChild(text);
    }
  }
}

let table = document.querySelector("table");
let data = Object.keys(mountains[0]);
generateTableHead(table, data);
generateTable(table, mountains);

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

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

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

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

// omitted for brevity

let table = document.querySelector("table");
let data = Object.keys(mountains[0]);
generateTable(table, mountains); // generate the table first
generateTableHead(table, data); // then the head

再次刷新浏览器:

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

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

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

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

总结

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

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

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

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

jQuery正逐渐消失。 Bootstrap将在版本5中删除它原生DOM API 越来越好了,替换以前用 jQuery 做的事情是可行的,没有(几乎)任何额外的依赖。

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

本教程的代码可在 Github 下载( https://github.com/valentinog... )。

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

欢迎继续阅读本专栏其它高赞文章:

本文首发微信公众号:jingchengyideng

欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入浅出密码学

深入浅出密码学

Christof Paar、Jan Pelzl / 马小婷 / 清华大学出版社 / 2012-9 / 59.00元

密码学的应用范围日益扩大,它不仅用于政府通信和银行系统等传统领域,还用于Web浏览器、电子邮件程序、手机、制造系统、嵌入式软件、智能建筑、汽车甚至人体器官移植等领域。今天的设计人员必须全面系统地了解应用密码学。 《深入浅出密码学——常用加密技术原理与应用》作者帕尔和佩尔茨尔长期执教于计算机科学与工程系,拥有十分丰富的应用密码学教学经验。本书可作为研究生和高年级本科生的教科书,也可供工......一起来看看 《深入浅出密码学》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具