一 Node类型
出现版本:DOM Level 1
Node 接口 在 JavaScript中被实现为 Node 类型,在除 IE之外的所有浏览器中都可以直接访问这个类型。
在 JavaScript 中,所有节点类型都继承 Node 类型,因此所有类型都共享相同的基本属性和方法
二 公共属性
在 JavaScript 中,所有节点类型都继承 Node 类型,因此所有类型都共享相同的基本属性和方法
- nodeType 属性:表示该节点的类型
由定义在 Node 类型上的 12 个数值 常量表示:
- Node.ELEMENT_NODE(1)
- Node.ATTRIBUTE_NODE(2)
- Node.TEXT_NODE(3)
- Node.CDATA_SECTION_NODE(4)
- Node.ENTITY_REFERENCE_NODE(5)
- Node.ENTITY_NODE(6)
- Node.PROCESSING_INSTRUCTION_NODE(7)
- Node.COMMENT_NODE(8)
- Node.DOCUMENT_NODE(9)
- Node.DOCUMENT_TYPE_NODE(10)
- Node.DOCUMENT_FRAGMENT_NODE(11)
- Node.NOTATION_NODE(12)
程序实现:节点类型可通过与这些常量比较来确定
if (someNode.nodeType == Node.ELEMENT_NODE){
alert("Node is an element.");
}
- nodeName属性
- nodeValue属性
- nodeName 与 nodeValue 保存着有关节点的信息
- 这两个属性的值完全取决于节点类型。
- 在使用 这两个属性前,最好先检测节点类型
if (someNode.nodeType == 1){ value = someNode.nodeName; // 会显示元素的标签名 } //在这个例子中,先检查了节点是不是元素。 //如果是,则将其 nodeName 的值赋给一个变量。 //对元素 而言,nodeName 始终等于元素的标签名,而 nodeValue 则始终为 null。
三 节点关系
- 节点:Node
- 属性:
- childNodes -> NodeList实例
- ownerDocument:一个指向代表整个文档的文档节点的指针
- 所有节点都被创建它们(或自己所在)的文档所拥有
- 获取节点长度:length
let count = someNode.childNodes.length;
- 判断是否存在某节点:hasChildNodes()
- 返回true:说明节点有一个或多个子节点
- 访问节点元素:
- 中括号[]
let firstChild = someNode.childNodes[0];
- 使用item()方法
let secondChild = someNode.childNodes.item(1);
- 中括号[]
- 将NodeList对象转换为数组
- Array.prototype.slice()
let arrayOfNodes = Array.prototype.slice.call(someNode.childNodes,0);
- Array.from()
let arrayOfNodes = Array.from(someNode.childNodes);
- Array.prototype.slice()
- 属性:
- 父节点: parentNode
- 关系:
- 第一个子节点:firstChild / xxx.childNodes[0]
- 最后一个子节点:lastChild / xxx.childNodes[xxx.childNodes.length -1 ]
- 同胞节点:使用previousSibling nextSibling在列表的节点间导航
- 第一个节点的previousSibling属性为null
- 最后一个节点的nextSibling属性为null
- childNodes中只有一个节点,则previousSibling和nextSibling属性为null
if (someNode.nextSibling === null){ alert("Last node in the parent's childNodes list."); } else if (someNode.previousSibling === null){ alert("First node in the parent's childNodes list."); }
四 操作节点
- appendChild()、insertBefore():在插入节点时不会删除任何已有节点
- replaceChild()、removeChild():被移除的节点从技术上说仍然被同一个文档所拥有,但文档中已经没有它的位置
- appendChild():用于在childNodes末尾添加节点
- 原理:添加新节点会更新相关的关系指针,包括父节点和之前的最后一个子节点,DOM树通过各种关系指针微信,一个节点也不会在文档中同时出现在两个或更多个地方
- 返回值:返回新添加的节点
- 使用场景:添加未存在的新节点 / 将已存在的节点转移到新位置
// appendChild()方法返回新添加的节点
let returnedNode = someNode.appendChild(newNode);
alert(returnedNode == newNode); // true
alert(someNode.lastChild == newNode); // true
// 假设 someNode 有多个子节点
let returnedNode = someNode.appendChild(someNode.firstChild);
alert(returnedNode == someNode.firstChild); // false
alert(returnedNode == someNode.lastChild); // true
- insertBefore():用于在childNodes的特定位置添加节点
- 参数:(2个)要插入的节点 参照节点
- 原理:要插入的节点会变成参照节点的前一个同胞节点,并被返回
// 如果参照节点是 null,则 insertBefore()与 appendChild()效果相同,如下面的例子所示:
// 作为最后一个子节点插入
returnedNode = someNode.insertBefore(newNode, null);
alert(newNode == someNode.lastChild); // true
// 作为新的第一个子节点插入
returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode); // true
alert(newNode == someNode.firstChild); // true
// 插入最后一个子节点前面
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length - 2]); // true
- replaceChild():替换节点
- 参数:(2个)要插入的节点 要替换的节点
- 返回:要替换的节点会被返回并从文档树中完全移除;要插入的节点会取而代之
- 原理:插入一个节点后,所有关系指针都会从被替换的节点复制过来
// 替换第一个子节点
let returnedNode = someNode.replaceChild(newNode, someNode.firstChild);
// 替换最后一个子节点
returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
- removeChild():移除节点
- 参数:要移除的节点
- 返回:被移除的节点会被返回
// 删除第一个子节点
let formerFirstChild = someNode.removeChild(someNode.firstChild);
// 删除最后一个子节点
let formerLastChild = someNode.removeChild(someNode.lastChild);
五 其他方法
- cloneNode()
- 参数:一个布尔值参数,表示是否深复制
- 深复制:传入true,即复制节点及其整个子 DOM 树
- 浅复制:传入false,则只会复制调用该方法的节点
- 返回:返回与调用它的节点一模一样的节点
- 参数:一个布尔值参数,表示是否深复制
孤儿节点(orphan):复制返回的节点属 于文档所有,但尚未指定父节点
可以通过 appendChild()、 insertBefore()或 replaceChild()方法把孤儿节点添加到文档中
<ul> <li>item 1</li> <li>item 2</li> <li>item 3</li> </ul>
// deepList 保存着 myList 的副本。这意味着 deepList 有 3 个列表项,每个列表
项又各自包含文本
let deepList = myList.cloneNode(true);
alert(deepList.childNodes.length); // 3(IE9 之前的版本)或 7(其他浏览器)
// shallowList 则保存着 myList 的浅副本,因此没有子节点
let shallowList = myList.cloneNode(false);
alert(shallowList.childNodes.length); // 0
// deepList.childNodes.length 的值会因 IE8 及更低版本和其他浏览器对空格的处理方式而不同。IE9之前的版本不会为空格创建节点。
cloneNode()方法不会复制添加到 DOM 节点的 JavaScript 属性,比如事件处理程序。
这个方法只复制 HTML 属性,以及可选地复制子节点。除此之外则一概不会复制。
- normalize()
- 作用:处理文档子树中的文本节点
- 操作:会检测这个节点的所有后代
- 不包含文本的文本节点 或 文本节点之间互为同胞关系
- 返回:
- 有空文本节点,将其删除
- 两个同胞节点是相邻的,则将其合并为一个文本节点