JavaScript - DOM
1. 查找节点
方法1. document.querySelector, document.querySelectorAll
方法2. document.getElementById, document.getElementsByClassName
2. 更新节点
前提是拿到要修改的DOM
方法1. 用innerHTML, 可以修改文本,甚至改变原本的标签结构,接受全文本。例如,p.innerHTML = 'ABC <span style="color:red">RED XYZ'。 此处有问题,如果写入的字符串是通过网络拿到了,要注意对字符编码来避免XSS攻击。
方法2. 用innerText或textContent可以自动对字符串编码,防止XSS。两者的区别在于读取属性时,innerText不返回隐藏元素的文本,而textContent返回所有文本。
// 获取<p id="p-id">...</p>
var p = document.getElementById('p-id');
// 设置文本:
p.innerText = '<script>alert("Hi")</script>';
// HTML被自动编码,无法设置一个<script>节点:
// <p id="p-id"><script>alert("Hi")</script></p>
注意:2.的方法1的p.innerHTML = 'ABC <span style="color:red">RED,假如去掉转义符\,在博客园上会执行。p.innerHTML = 'ABC RED'
3. 插入节点
方法1. appendChild,把一个子节点添加到父节点的最后一个子节点。
方法2. parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前。
3.1 appendChild,使用原有的节点。
<!-- HTML结构 -->
<p id="js">JavaScript</p>
<div id="list">
<p id="java">Java</p>
<p id="python">Python</p>
<p id="scheme">Scheme</p>
</div>
var
js = document.getElementById('js'),
list = document.getElementById('list');
list.appendChild(js);
<!-- HTML结构 -->
<div id="list">
<p id="java">Java</p>
<p id="python">Python</p>
<p id="scheme">Scheme</p>
<p id="js">JavaScript</p>
</div>
插入的js节点已经存在于当前的文档树,因此这个节点首先会从原先的位置删除,再插入到新的位置。更多的时候,用方法2,创建新节点。
3.2 appendChild,创建新节点,再插入。
var
list = document.getElementById('list'),
haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);
<!-- HTML结构 -->
<div id="list">
<p id="java">Java</p>
<p id="python">Python</p>
<p id="scheme">Scheme</p>
<p id="haskell">Haskell</p>
</div>
彩蛋:动态创建一个节点然后添加到DOM树中,可以实现很多功能。举个例子,下面的代码动态创建了一个<style>节点,然后把它添加到节点的末尾,这样就动态地给文档添加了新的CSS定义。
var d = document.createElement('style');
d.setAttribute('type', 'text/css');
d.innerHTML = 'p { color: red }';
document.getElementsByTagName('head')[0].appendChild(d);
可以在Chrome的控制台执行上述代码,观察页面样式的变化。
4. 删除节点
方法1. 要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉:
// 拿到待删除节点:
var self = document.getElementById('to-be-removed');
// 拿到父节点:
var parent = self.parentElement;
// 删除:
var removed = parent.removeChild(self);
removed === self; // true
注意到删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。
问题:当遍历一个父节点的子节点并进行删除操作时,要注意,children属性是一个只读属性,并且它在子节点变化时会实时更新。
<div id="parent">
<p>First</p>
<p>Second</p>
</div>
var parent = document.getElementById('parent');
parent.removeChild(parent.children[0]); //删除后只剩下一个元素,索引为0
parent.removeChild(parent.children[1]); // <-- 浏览器报错