节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在 DOM 中,节点使用 node 来表示。HTML DOM 树中的所有节点均可以通过 javaScript 进行访问,所有 HTML 节点均可以被修改,也可以创建新或删除节点。 学习节点操作后我们可以利用 DOM 提供的方法获取元素也可以利用节点的层级关系获取元素。前者逻辑性不强比较繁琐,后者逻辑性强但是兼容性稍差。
一般地,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和 nodeValue(节点值) 这三个基本属性。
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(文本节点包括文字、空格、换行等)
我们主要操作的是元素节点。
节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。我们可以利用节点的层级关系获得相应的节点。
1、父级节点
// node.parentNode属性返回某节点的父节点,如果指定节点没有父节点返回null。
var ul = li.parentNode;
2、子级节点
(1)node.childNodes
返回指定节点的所有类型子节点的集合,包括元素节点、文本节点等。如果只想要获得里面的元素节点则需要专门处理,所以一般不提倡使用。
var ul0 = document.querySelector('ul');
var ul = [];
for (var i = 0; i < ul0.childNodes.length; i++) {
if (ul0.childNodes[i].nodeType == 1) {
ul.push(ul0.childNodes[i]);
}
}
(2)node.children
是一个只读属性,返回指定节点的所有子元素节点,其余类型的节点不反回。
var li = ul0.children[1]; // 获取ul0内的第二个子元素li
(3)node.firstChild
和 node.lastChild
分别返回指定节点的第一个和最后一个任何类型的子节点,找不到则为 null 。
(4)node.firstElementChild
和 node.lastElementChild
分别返回指定节点的第一个和最后一个子元素节点,找不到则为 null 。但是他们有兼容性问题,ie9 以上才支持。解决方案:
// 第一个子元素节点
var first = ul0.children[0];
var last = ul0.children[ul0.children.length - 1];
3、兄弟节点
(1)node.nextSibling
和 node.previousSibling
分别返回指定节点的上一个和下一个任何类型的兄弟节点,找不到则为 null 。
(2)node.nextElementSibling
和 node.previousElementSibling
分别返回指定节点的上一个和下一个兄弟元素节点,找不到则为 null 。但是他们存在兼容性问题,ie9 以上才支持。解决方案:
function getNextElementSibling(element) {
while (element = element.nextSibling) {
if (element.nodeType === 1) {
return element;
}
}
return null;
}
创建和添加节点
(1)创建节点: document.createElement('tagName')
方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是我们根据需要动态生成的,所以我们也称为动态创建元素节点。
(2)添加节点: 添加节点可以将一个节点添加到指定父节点的子节点列表末尾。也可以将一个节点添加到父节点的指定子节点前面。 使用的方法如下:
var ul = document.querySelector('ul');
var li = document.createElement('li');
ul.appendChild(li); // 将创建的li元素添加到ul的最后面,相当于:after伪类
ul.insertBefore(li, ul.children[0]); // 添加到ul第一个子元素的前面
删除节点
node.removeChild(child)
方法从 DOM 中删除一个子节点并返回删除的子节点。
节点克隆(复制)
node.cloneNode()
方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点。
- 如果括号参数为空或者为 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
如果括号参数为 true,则是深度拷贝,会复制节点本身及里面的所有子节点。
三种动态创建节点区别
- document.write()
- element.innerHTML
- document.createElement()
区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘。
- innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘。
- innerHTML 创建多个元素效率更高,但是不要拼接字符串,采取数组形式拼接,否则因为字符串是不可变的导致不断开辟内存空间,效率会很低。
- createElement() 创建多个元素效率稍微低一点点,但是相对于 innerHTML 结构更清晰。