2026/10/6 1:51:36

Modern JavaScript Tutorial:用 DOM 插入方法实现表格按列排序(Sort the Table)

Modern JavaScript Tutorial:用 DOM 插入方法实现表格按列排序(Sort the Table) 文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载导读本文源自 Modern JavaScript Tutorial 中修改文档Modifying the document章节的经典练习任务 12-sort-table/task.md给定一张包含 Name、Surname、Age 三列的 HTML 表格要求编写 JavaScript 代码按name列排序。其标准解法的精妙之处在于不需要删除或重建任何行只需借助tbody.append(...)把已排序的行重新插入 DOM浏览器会自动把它们从原位置搬走。读完本文你将掌握table.tBodies、table.rows、row.cells等表格专用 DOM 导航属性、localeCompare字符串比较以及基于append的行重排技巧并能把它推广到任意列、数字列等排序场景。一、任务描述与初始表格结构任务给出的 HTML 如下source.view/index.html 中是等价的空白待填写版本table thead tr thName/ththSurname/ththAge/th /tr /thead tbody tr tdJohn/tdtdSmith/tdtd10/td /tr tr tdPete/tdtdBrown/tdtd15/td /tr tr tdAnn/tdtdLee/tdtd5/td /tr tr td.../tdtd.../tdtd.../td /tr /tbody /table注意两点表格包含明确的thead与tbody结构表头行th不需要参与排序任务明确说明表中可能还有更多行There may be more rows in it因此排序代码必须与行数无关不能写死只排 3 行。二、官方解法三步算法任务的标准答案非常简短却蕴含了 DOM 操作的核心技巧。官方解答 solution.md 给出了带注释的完整代码let sortedRows Array.from(table.tBodies[0].rows) // 1 .sort((rowA, rowB) rowA.cells[0].innerHTML.localeCompare(rowB.cells[0].innerHTML)); table.tBodies[0].append(...sortedRows); // (3)逐行拆解算法步骤取出tbody中所有trtable.tBodies[0].rows返回该表格体下所有数据行按第一个td的内容排序比较函数读取row.cells[0].innerHTML即 Name 列文本用localeCompare做字符串比较按正确顺序重新插入节点table.tBodies[0].append(...sortedRows)把排序后的行依次追加到 tbody 末尾。官方解答特别强调了一个关键点我们不需要移除行元素只需要重新插入它们会自动离开原来的位置We dont have to remove row elements, just re-insert, they leave the old place automatically。这正是 DOM 中节点是活对象这一特性的体现——一个元素在文档中只能有一个位置被重新插入到新位置时旧位置自然被腾出。完整可运行版本见 solution.view/index.html其脚本部分与上述代码一致。三、前置知识表格专用的 DOM 导航属性要理解这段代码先要掌握表格的专用 DOM 接口。在 03-dom-navigation/article.mdDOM 导航章节中有明确说明table.rows-- the collection oftrelements of the table.table.tBodies-- the collection oftbodyelements (can be many according to the standard, but there will always be at least one -- even if it is not in the source HTML, the browser will put it in the DOM).即table.rows表格中所有tr的集合HTMLCollection动态集合table.tBodies表格中所有tbody的集合。按标准允许有多个 tbody但 DOM 中永远至少有一个——即便源码 HTML 没有写tbody浏览器也会自动补出row.cells某一行tr内所有td/th单元格的集合cells[0]即该行第一个单元格。任务解答中的table.tBodies[0].rows因此等价于取第一个也是唯一的tbody 里全部数据行。之所以不直接用table.rows是因为table.rows会把thead里的表头tr也算进来而排序时我们必须跳过表头行。官方解答末尾的 P.S. 也印证了这一背景知识In our case, theres an explicittbodyin the table, but even if HTML table doesnt havetbody, the DOM structure always has it.——即便 HTML 中没有显式tbodyDOM 结构中也总是存在它所以tBodies[0]的写法是安全的。四、两个必须注意的细节1. 为什么需要Array.from(...)table.tBodies[0].rows返回的是HTMLCollection或 rows 集合它是一个动态的、类数组对象本身没有数组的sort方法。因此必须先通过Array.from(...)把它转换成真正的数组才能调用Array.prototype.sort。2. 为什么用localeCompare而不是比较(rowA, rowB) rowA.cells[0].innerHTML.localeCompare(rowB.cells[0].innerHTML)String.prototype.localeCompare按字典序locale 感知比较两个字符串返回负数、0 或正数恰好满足Array.prototype.sort比较器的契约。对John、Pete、Ann这类名字排序它能得到符合人们直觉的字母序结果。若换成a b这种布尔比较既不能返回负数/正数语义又无法正确处理本地化字符排序结果会不可靠。五、核心机制append如何完成移动而非复制第三步table.tBodies[0].append(...sortedRows)是整段代码的灵魂。它依赖的append方法在 07-modifying-document/article.md 的插入方法Insertion methods一节中有系统介绍node.append(...nodes or strings)-- append nodes or stringsat the endofnodenode.prepend(...nodes or strings)-- insert nodes or stringsat the beginningofnodenode.before(...nodes or strings)-- insert nodes or stringsbeforenodenode.after(...nodes or strings)-- insert nodes or stringsafternodenode.replaceWith(...nodes or strings)-- replacesnodewith the given nodes or strings.这些方法的参数是任意数量的 DOM 节点或文本字符串an arbitrary list of DOM nodes to insert, or text strings。示意图 before-prepend-append-after.svg 直观展示了各插入点位置关键语义在于插入的是节点本身而不是节点的副本。当append(...sortedRows)把某个tr追加到 tbody 末尾时由于该节点已在文档中拥有父节点浏览器会自动把它从原位置移除再插入新位置——因此无需先remove()再插入也就不会出现行重复或顺序错乱。这一先取后插、自动搬家的模式是 DOM 插入方法区别于克隆 删除的传统做法的最大优势。六、推广与思考把解法泛化到更多场景掌握了核心三步后可以自然推广1. 按任意列排序把比较器中的cells[0]换成cells[index]即可按第 index 列排序例如 Age 列cells[2]。若按数值列排序innerHTML是字符串需要先转成数字再比较let sortedRows Array.from(table.tBodies[0].rows) .sort((rowA, rowB) Number(rowA.cells[2].innerHTML) - Number(rowB.cells[2].innerHTML)); table.tBodies[0].append(...sortedRows);字符串形式的10、5若直接用localeCompare会得到10 5的字典序结果与数值直觉相悖因此数值列必须显式转换。2. 大小写与本地化localeCompare已内置大小写与 locale 规则但对特定需求如忽略大小写、按中文拼音可传入参数或改用toLowerCase()预处理(a, b) a.cells[0].innerHTML.toLowerCase().localeCompare(b.cells[0].innerHTML.toLowerCase())3. 复用排序结果sortedRows是一次性快照数组重排后表格即完成排序若需多次排序如点击表头切换升降序只需把排序方向取反再执行一次append(...)即可。七、小结这个任务的本质是把表格排序这一业务需求翻译成四段 DOM 知识点的组合运用知识点在本任务中的作用table.tBodies[0]定位数据体天然避开表头行...rowsArray.from()拿到可排序的真实数组快照row.cells[0].innerHTMLlocaleCompare提取单元格文本并按字典序比较tbody.append(...sortedRows)把排序结果重新插入节点自动搬家无需手动删除对照仓库中的原始材料你可以继续深入task.md 是题目原文solution.md 是带注释的官方解答solution.view/index.html 是可运行成品相关的系统知识分别见 03-dom-navigation/article.md表格导航属性与 07-modifying-document/article.md插入方法。把这套快照排序 重插移动的写法吃透就能举一反三地处理各种基于 DOM 的排序与重排需求。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐现代 JavaScript 教程实战用 DOM 插入方法实现表格按列排序基于 en.javascript.info 的 Sort the Table 习题现代 JavaScript 教程实战用 DOM 插入方法实现表格按列排序基于 en.javascript.info 的 Sort the Table 习题文档/教程前端Modern JavaScript Tutorial 实战用 insertAdjacentHTML 在列表中精准插入 HTML 节点Modern JavaScript Tutorial 实战用 insertAdjacentHTML 在列表中精准插入 HTML 节点 导读 本篇基于 Mode文档/教程前端Modern JavaScript Tutorial 实战用 insertAdjacentHTML 向列表插入 HTML —— append-to-list 任务全解析Modern JavaScript Tutorial 实战用 insertAdjacentHTML 向列表插入 HTML —— append to list文档/教程前端上一篇echarts-for-weixin项目架构深度解析下一篇NodeGraphQt实战手把手教你创建第一个节点可视化应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考