Skip to content

Commit 6a1696f

Browse files
committed
docs(dom): add text
1 parent 0a7f12f commit 6a1696f

2 files changed

Lines changed: 213 additions & 1 deletion

File tree

chapters.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
- dom/document.md: Document 节点
5252
- dom/element.md: Element 节点
5353
- dom/attributes.md: 属性的操作
54-
- dom/globaleventhandlers.md: GlobalEventHandlers 接口
54+
- dom/text.md: Text 节点和 DocumentFragment 节点
55+
- dom/globaleventhandlers.md: GlobalEventHandlers 接
5556
- bom/: 浏览器模型
5657
- bom/cookie.md: Cookie
5758
- bom/same-origin.md: 同源限制

docs/dom/text.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# Text 节点和 DocumentFragment 节点
2+
3+
## Text 节点的概念
4+
5+
文本节点(`Text`)代表元素节点(`Element`)和属性节点(`Attribute`)的文本内容。如果一个节点只包含一段文本,那么它就有一个文本子节点,代表该节点的文本内容。
6+
7+
通常我们使用父节点的`firstChild``nextSibling`等属性获取文本节点,或者使用`Document`节点的`createTextNode`方法创造一个文本节点。
8+
9+
```javascript
10+
// 获取文本节点
11+
var textNode = document.querySelector('p').firstChild;
12+
13+
// 创造文本节点
14+
var textNode = document.createTextNode('Hi');
15+
document.querySelector('div').appendChild(textNode);
16+
```
17+
18+
浏览器原生提供一个`Text`构造函数。它返回一个文本节点实例。它的参数就是该文本节点的文本内容。
19+
20+
```javascript
21+
// 空字符串
22+
var text1 = new Text();
23+
24+
// 非空字符串
25+
var text2 = new Text('This is a text node');
26+
```
27+
28+
注意,由于空格也是一个字符,所以哪怕只有一个空格,也会形成文本节点。比如,`<p> </p>`包含一个空格,它的子节点就是一个文本节点。
29+
30+
文本节点除了继承`Node`接口,还继承了`CharacterData`接口。`Node`接口的属性和方法请参考《Node 接口》一章,这里不再重复介绍了,以下的属性和方法大部分来自`CharacterData`接口。
31+
32+
## Text 节点的属性
33+
34+
### data
35+
36+
`data`属性等同于`nodeValue`属性,用来设置或读取文本节点的内容。
37+
38+
```javascript
39+
// 读取文本内容
40+
document.querySelector('p').firstChild.data
41+
// 等同于
42+
document.querySelector('p').firstChild.nodeValue
43+
44+
// 设置文本内容
45+
document.querySelector('p').firstChild.data = 'Hello World';
46+
```
47+
48+
### wholeText
49+
50+
`wholeText`属性将当前文本节点与毗邻的文本节点,作为一个整体返回。大多数情况下,`wholeText`属性的返回值,与`data`属性和`textContent`属性相同。但是,某些特殊情况会有差异。
51+
52+
举例来说,HTML 代码如下。
53+
54+
```html
55+
<p id="para">A <em>B</em> C</p>
56+
```
57+
58+
这时,文本节点的`wholeText`属性和`data`属性,返回值相同。
59+
60+
```javascript
61+
var el = document.getElementById('para');
62+
el.firstChild.wholeText // "A "
63+
el.firstChild.data // "A "
64+
```
65+
66+
但是,一旦移除`<em>`节点,`wholeText`属性与`data`属性就会有差异,因为这时其实`<p>`节点下面包含了两个毗邻的文本节点。
67+
68+
```javascript
69+
el.removeChild(para.childNodes[1]);
70+
el.firstChild.wholeText // "A C"
71+
el.firstChild.data // "A "
72+
```
73+
74+
### length
75+
76+
`length`属性返回当前文本节点的文本长度。
77+
78+
```javascript
79+
(new Text('Hello')).length // 5
80+
```
81+
82+
### nextElementSibling,previousElementSibling
83+
84+
`nextElementSibling`属性返回紧跟在当前文本节点后面的那个同级元素节点。如果取不到元素节点,则返回`null`
85+
86+
```javascript
87+
// HTML 为
88+
// <div>Hello <em>World</em></div>
89+
var tn = document.querySelector('div').firstChild;
90+
tn.nextElementSibling
91+
// <em>World</em>
92+
```
93+
94+
`previousElementSibling`属性返回当前文本节点前面最近的同级元素节点。如果取不到元素节点,则返回`null:`
95+
96+
## Text 节点的方法
97+
98+
### appendData(),deleteData(),insertData(),replaceData(),subStringData()
99+
100+
以下5个方法都是编辑`Text`节点文本内容的方法。
101+
102+
- `appendData()`:在`Text`节点尾部追加字符串。
103+
- `deleteData()`:删除`Text`节点内部的子字符串,第一个参数为子字符串开始位置,第二个参数为子字符串长度。
104+
- `insertData()`:在`Text`节点插入字符串,第一个参数为插入位置,第二个参数为插入的子字符串。
105+
- `replaceData()`:用于替换文本,第一个参数为替换开始位置,第二个参数为需要被替换掉的长度,第三个参数为新加入的字符串。
106+
- `subStringData()`:用于获取子字符串,第一个参数为子字符串在`Text`节点中的开始位置,第二个参数为子字符串长度。
107+
108+
```javascript
109+
// HTML 代码为
110+
// <p>Hello World</p>
111+
var pElementText = document.querySelector('p').firstChild;
112+
113+
pElementText.appendData('!');
114+
// 页面显示 Hello World!
115+
pElementText.deleteData(7, 5);
116+
// 页面显示 Hello W
117+
pElementText.insertData(7, 'Hello ');
118+
// 页面显示 Hello WHello
119+
pElementText.replaceData(7, 5, 'World');
120+
// 页面显示 Hello WWorld
121+
pElementText.substringData(7, 10);
122+
// 页面显示不变,返回"World "
123+
```
124+
125+
### remove()
126+
127+
`remove`方法用于移除当前`Text`节点。
128+
129+
```javascript
130+
// HTML 代码为
131+
// <p>Hello World</p>
132+
document.querySelector('p').firstChild.remove()
133+
// 现在 HTML 代码为
134+
// <p></p>
135+
```
136+
137+
### splitText(),normalize()
138+
139+
`splitText`方法将`Text`节点一分为二,变成两个毗邻的`Text`节点。它的参数就是分割位置(从零开始),分割到该位置的字符前结束。如果分割位置不存在,将报错。
140+
141+
分割后,该方法返回分割位置后方的字符串,而原`Text`节点变成只包含分割位置前方的字符串。
142+
143+
```javascript
144+
// html 代码为 <p id="p">foobar</p>
145+
var p = document.getElementById('p');
146+
var textnode = p.firstChild;
147+
148+
var newText = textnode.splitText(3);
149+
newText // "bar"
150+
textnode // "foo"
151+
```
152+
153+
`normalize`方法可以将毗邻的两个`Text`节点合并。
154+
155+
接上面的例子,`splitText`方法将一个`Text`节点分割成两个,`normalize`方法可以实现逆操作,将它们合并。
156+
157+
```javascript
158+
p.childNodes.length // 2
159+
160+
// 将毗邻的两个 Text 节点合并
161+
p.normalize();
162+
p.childNodes.length // 1
163+
```
164+
165+
## DocumentFragment 节点
166+
167+
`DocumentFragment`节点代表一个文档的片段,本身就是一个完整的 DOM 树形结构。它没有父节点,`parentNode`返回`null`,但是可以插入任意数量的子节点。它不属于当前文档,操作`DocumentFragment`节点,要比直接操作 DOM 树快得多。
168+
169+
它一般用于构建一个 DOM 结构,然后插入当前文档。`document.createDocumentFragment`方法,以及浏览器原生的`DocumentFragment`构造函数,可以创建一个空的`DocumentFragment`节点。然后再使用其他 DOM 方法,向其添加子节点。
170+
171+
```javascript
172+
var docFrag = document.createDocumentFragment();
173+
// 等同于
174+
var docFrag = new DocumentFragment();
175+
176+
var li = document.createElement('li');
177+
li.textContent = 'Hello World';
178+
docFrag.appendChild(li);
179+
180+
document.querySelector('ul').appendChild(docFrag);
181+
```
182+
183+
上面代码创建了一个`DocumentFragment`节点,然后将一个`li`节点添加在它里面,最后将`DocumentFragment`节点移动到原文档。
184+
185+
注意,`DocumentFragment`节点本身不能被插入当前文档。当它作为`appendChild()``insertBefore()``replaceChild()`等方法的参数时,是它的所有子节点插入当前文档,而不是它自身。一旦`DocumentFragment`节点被添加进当前文档,它自身就变成了空节点(`textContent`属性为空字符串),可以被再次使用。如果想要保存`DocumentFragment`节点的内容,可以使用`cloneNode`方法。
186+
187+
```javascript
188+
document
189+
.queryselector('ul')
190+
.appendChild(docFrag.cloneNode(true));
191+
```
192+
193+
上面这样添加`DocumentFragment`节点进入当前文档,不会清空`DocumentFragment`节点。
194+
195+
下面是一个例子,使用`DocumentFragment`反转一个指定节点的所有子节点的顺序。
196+
197+
```javascript
198+
function reverse(n) {
199+
var f = document.createDocumentFragment();
200+
while(n.lastChild) f.appendChild(n.lastChild);
201+
n.appendChild(f);
202+
}
203+
```
204+
205+
`DocumentFragment`节点对象没有自己的属性和方法,全部继承自`Node`节点和`ParentNode`接口。也就是说,`DocumentFragment`节点比`Node`节点多出以下四个属性。
206+
207+
- `children`:返回一个动态的`HTMLCollection`集合对象,包括当前`DocumentFragment`对象的所有子元素节点。
208+
- `firstElementChild`:返回当前`DocumentFragment`对象的第一个子元素节点,如果没有则返回`null`
209+
- `lastElementChild`:返回当前`DocumentFragment`对象的最后一个子元素节点,如果没有则返回`null`
210+
- `childElementCount`:返回当前`DocumentFragment`对象的所有子元素数量。
211+

0 commit comments

Comments
 (0)