查找节点
document.getElementById()
可以直接定位唯一的一个DOM节点。
document.getElementsByTagName()
和document.getElementsByClassName()
总是返回一组DOM节点。要精确地选择DOM,可以先定位父节点,再从父节点开始选择,以缩小范围。
// 返回ID为'test'的节点: var test = document.getElementById('test'); // 先定位ID为'test-table'的节点,再返回其内部所有tr节点: var trs = document.getElementById('test-table').getElementsByTagName('tr'); // 先定位ID为'test-div'的节点,再返回其内部所有class包含red的节点: var reds = document.getElementById('test-div').getElementsByClassName('red'); // 获取节点test下的所有直属子节点: var cs = test.children; // 获取节点test下第一个、最后一个子节点: var first = test.firstElementChild; var last = test.lastElementChild;
使用querySelector()
和querySelectorAll()
,需要了解selector语法,然后使用条件来获取节点
// 通过querySelector获取ID为q1的节点: var q1 = document.querySelector('#q1'); // 通过querySelectorAll获取q1节点内的符合条件的所有节点: var ps = q1.querySelectorAll('div.highlighted > p');
严格地讲,我们这里的DOM节点是指Element
,但是DOM节点实际上是Node
,在HTML中,Node
包括Element
、Comment
、CDATA_SECTION
等很多种,以及根节点Document
类型,但是,绝大多数时候我们只关心Element
,也就是实际控制页面结构的Node
,其他类型的Node
忽略即可。根节点Document
已经自动绑定为全局变量document
。
更新DOM
修改节点的文本,方式有两种
一种是修改innerHTML
另一种是修改innerText或者textContent
innerHTML不仅可以写入单纯的文本,还能写入HTML代码片段。所以在使用时,如果字符串是通过网络拿到,要注意对字符编码来避免XSS攻击
innerText或者textContent可以自动对字符串进行HTML编码,保证无法设置任何HTML标签
插入DOM
如果DOM节点为空,例如<div></div>,直接使用 innerHTML = '<span>child</span>' 就可以修改DOM节点的内容
如果DOM节点不为空,就不能这样做了,因为innerHTML会替换到原来所有的节点。
有两种方法:
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>
把<p id="js">JavaScript</p>
添加到<div id="list">
的最后一项:
var js = document.getElementById('js'), list = document.getElementById('list'); list.appendChild(js);
HTML结构变成了这样
<!-- 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>
2.把一个子节点添加到指定位置 parentElement.insertBefore(newElement, referenceElement);
子节点会插入到referenceElement
之前。
<!-- HTML结构 --> <div id="list"> <p id="java">Java</p> <p id="python">Python</p> <p id="scheme">Scheme</p> </div>
var list = document.getElementById('list'), ref = document.getElementById('python'), haskell = document.createElement('p'); haskell.id = 'haskell'; haskell.innerText = 'Haskell'; list.insertBefore(haskell, ref);
改变后的HTML结构
<!-- HTML结构 --> <div id="list"> <p id="java">Java</p> <p id="haskell">Haskell</p> <p id="python">Python</p> <p id="scheme">Scheme</p> </div>
删除DOM
删除节点,需要获得节点自身和它的父元素,然后调用父节点的removeChild把自己删掉
// 拿到待删除节点: var self = document.getElementById('to-be-removed'); // 拿到父节点: var parent = self.parentElement; // 删除: var removed = parent.removeChild(self); removed === self; // true
注意到删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。
当你遍历一个父节点的子节点并进行删除操作时,要注意,children
属性是一个只读属性,并且它在子节点变化时会实时更新。
例如,对于如下HTML结构:
<div id="parent"> <p>First</p> <p>Second</p> </div>
当我们用如下代码删除子节点时:
var parent = document.getElementById('parent'); parent.removeChild(parent.children[0]); parent.removeChild(parent.children[1]); // <-- 浏览器报错
浏览器报错:parent.children[1]
不是一个有效的节点。原因就在于,当<p>First</p>
节点被删除后,parent.children
的节点数量已经从2变为了1,索引[1]
已经不存在了。
因此,删除多个节点时,要注意children
属性时刻都在变化。
本来来自于廖雪峰的JS教程https://www.liaoxuefeng.com/