前言
在 DOM 树中,最不起眼却又无处不在的就是 Text 节点。每当你写下 <div>Hello</div> 时,那个 "Hello" 并不是 div 的属性,而是一个实实在在的 Text 类型子节点。掌握 Text 节点的精细化操作,能让你在处理文本交互时比别人更进一步。
一、 Text 节点的基本特征
Text 节点是 DOM 树中的“叶子”,它承载着纯文本内容。
nodeType: 3nodeName: "#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. 为什么 nodeValue 和 data 是等价的?
参考回答:
在 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 攻击的一种天然屏障。