DOM-你所不知道的 Text 节点深度指南

134 阅读2分钟

前言

在 DOM 树中,最不起眼却又无处不在的就是 Text 节点。每当你写下 <div>Hello</div> 时,那个 "Hello" 并不是 div 的属性,而是一个实实在在的 Text 类型子节点。掌握 Text 节点的精细化操作,能让你在处理文本交互时比别人更进一步。

一、 Text 节点的基本特征

Text 节点是 DOM 树中的“叶子”,它承载着纯文本内容。

  • nodeType: 3
  • nodeName: "#text"
  • nodeValue / data: 获取或设置节点包含的文本。
  • 无子节点: 它无法包含任何其他类型的节点。

创建文本节点

let textNode = document.createTextNode("Hello World!");
// 此时它还在内存中,需要 appendChild 到某个元素下
document.body.appendChild(textNode);

二、 文本操作:不仅仅是字符串拼接

Text 接口提供了一系列类似字符串操作的方法,但在 DOM 层面直接操作它们比重新设置 innerText 性能更高(因为它不会引起整个元素的重新解析)。

方法描述
appendData(text)在文本末尾追加内容。
insertData(offset, text)在指定位置插入文本。
deleteData(offset, count)从 offset 位置开始删除count长度的字符。
replaceData(offset, count, text)用 text 替换从位置 offset 到 offset + count 的文本。
substringData(offset, count)提取从位置 offset 到 offset + count 的文本。

三、 高阶特性:拆分与合并

这是 Text 节点最独特的地方,常用于搜索关键字高亮或文本分段处理。

1. splitText(offset):节点拆分

该方法会将一个文本节点拆分为两个同胞文本节点。原节点保留 offset 之前的内容,新节点包含之后的内容。

let div = document.createElement("div");
div.textContent = "HelloWorld";
let textNode = div.firstChild;

let newNode = textNode.splitText(5); 
console.log(textNode.data); // "Hello"
console.log(newNode.data);  // "World"

2. normalize():节点合并

这是定义在 Node 类型上的方法,但在处理 Text 节点时最常用。它会将相邻的文本节点合并为一个,并删除空的文本节点。

// 承接上面的例子
div.normalize();
console.log(div.childNodes.length); // 1 (两个节点又变回了一个)

四、 常见问题与坑点

1. 为什么 nodeValuedata 是等价的?

参考回答:

Node 接口中定义了 nodeValue 属性,而在 CharacterData 接口(Text 的父接口)中定义了 data。对于文本节点来说,它们指向的是同一块内存。在实际开发中,推荐使用 data,语义更明确。

2. 空白字符也是 Text 节点吗?

参考回答:

是的!在 HTML 中,标签之间的换行和空格在现代浏览器中都会被解析为 Text 节点(nodeValue 为 "\n ")。这就是为什么 childNodes.length 往往比你预想的要大的原因。

3. 如何安全地在文本中显示 HTML 代码?

参考回答:

Text 节点会自动转义 HTML。如果你通过 createTextNode("<b>Hi</b>") 创建节点,页面上会直接显示字符串 <b>Hi</b>,而不会显示加粗的文本。这是预防 XSS 攻击的一种天然屏障。