节点类型与属性
在JavaScript中,节点是DOM树的基本组成单位,不同类型的节点具有不同的属性和行为。理解节点类型及其属性对于操作DOM至关重要。
节点类型概述
DOM规范定义了多种节点类型,每种类型对应一个数值常量:
Node.ELEMENT_NODE (1)
Node.ATTRIBUTE_NODE (2)
Node.TEXT_NODE (3)
Node.CDATA_SECTION_NODE (4)
Node.PROCESSING_INSTRUCTION_NODE (7)
Node.COMMENT_NODE (8)
Node.DOCUMENT_NODE (9)
Node.DOCUMENT_TYPE_NODE (10)
Node.DOCUMENT_FRAGMENT_NODE (11)
可以通过节点的nodeType
属性判断其类型:
const element = document.createElement('div');
console.log(element.nodeType === Node.ELEMENT_NODE); // true
console.log(element.nodeType); // 1
元素节点
元素节点是最常见的节点类型,表示HTML或XML文档中的标签。其特点包括:
nodeType
为1nodeName
返回标签名(大写)- 拥有
tagName
属性 - 可以包含子节点和属性
const div = document.createElement('div');
div.id = 'container';
div.className = 'box';
div.setAttribute('data-custom', 'value');
console.log(div.nodeName); // "DIV"
console.log(div.tagName); // "DIV"
console.log(div.id); // "container"
console.log(div.className); // "box"
console.log(div.getAttribute('data-custom')); // "value"
文本节点
文本节点包含文档中的文本内容:
nodeType
为3nodeName
返回"#text"- 数据存储在
nodeValue
或data
属性中
const textNode = document.createTextNode('Hello World');
console.log(textNode.nodeType); // 3
console.log(textNode.nodeName); // "#text"
console.log(textNode.data); // "Hello World"
console.log(textNode.nodeValue); // "Hello World"
// 修改文本内容
textNode.appendData('!');
textNode.nodeValue = 'Changed text';
属性节点
属性节点表示元素的属性,但在现代DOM操作中很少直接使用:
nodeType
为2nodeName
返回属性名nodeValue
返回属性值
const attr = document.createAttribute('custom');
attr.value = 'some value';
console.log(attr.nodeType); // 2
console.log(attr.nodeName); // "custom"
console.log(attr.nodeValue); // "some value"
注释节点
注释节点表示HTML文档中的注释:
nodeType
为8nodeName
返回"#comment"- 注释内容存储在
nodeValue
或data
属性中
const comment = document.createComment('This is a comment');
console.log(comment.nodeType); // 8
console.log(comment.nodeName); // "#comment"
console.log(comment.data); // "This is a comment"
文档节点
文档节点表示整个文档:
nodeType
为9nodeName
返回"#document"- 是DOM树的根节点
console.log(document.nodeType); // 9
console.log(document.nodeName); // "#document"
console.log(document.documentElement); // <html>元素
文档片段节点
文档片段是轻量级的文档对象,用于高效地操作多个节点:
nodeType
为11nodeName
返回"#document-fragment"- 不在主DOM树中呈现
const fragment = document.createDocumentFragment();
const ul = document.createElement('ul');
for (let i = 0; i < 3; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i + 1}`;
fragment.appendChild(li);
}
ul.appendChild(fragment);
document.body.appendChild(ul);
节点属性与方法
所有节点类型都继承自Node接口,共享以下常用属性和方法:
基础属性
const element = document.getElementById('example');
console.log(element.nodeName); // 节点名称
console.log(element.nodeType); // 节点类型
console.log(element.nodeValue); // 节点值
console.log(element.parentNode); // 父节点
console.log(element.childNodes); // 子节点列表
console.log(element.firstChild); // 第一个子节点
console.log(element.lastChild); // 最后一个子节点
console.log(element.previousSibling); // 前一个兄弟节点
console.log(element.nextSibling); // 后一个兄弟节点
操作方法
// 创建和添加节点
const newElement = document.createElement('div');
const textNode = document.createTextNode('Some text');
newElement.appendChild(textNode);
// 克隆节点
const clonedNode = newElement.cloneNode(true); // 深度克隆
// 插入节点
const referenceNode = document.getElementById('reference');
referenceNode.parentNode.insertBefore(newElement, referenceNode);
// 替换节点
referenceNode.parentNode.replaceChild(clonedNode, referenceNode);
// 移除节点
clonedNode.parentNode.removeChild(clonedNode);
节点遍历
DOM提供了多种遍历节点树的方法:
// 深度优先遍历
function traverse(node) {
console.log(node.nodeName);
for (let i = 0; i < node.childNodes.length; i++) {
traverse(node.childNodes[i]);
}
}
// 使用TreeWalker API
const walker = document.createTreeWalker(
document.body,
NodeFilter.SHOW_ELEMENT,
null,
false
);
let currentNode;
while (currentNode = walker.nextNode()) {
console.log(currentNode.tagName);
}
现代DOM操作
现代JavaScript提供了更简洁的DOM操作方式:
// 查询选择
const elements = document.querySelectorAll('.class-selector');
const element = document.querySelector('#id-selector');
// classList操作
element.classList.add('new-class');
element.classList.remove('old-class');
element.classList.toggle('active');
// 数据集访问
element.dataset.customValue = 'data';
// 样式操作
element.style.setProperty('--custom-property', 'value');
节点比较
可以使用isEqualNode
和isSameNode
方法比较节点:
const div1 = document.createElement('div');
div1.className = 'box';
const div2 = div1.cloneNode(true);
console.log(div1.isEqualNode(div2)); // true
console.log(div1.isSameNode(div2)); // false
console.log(div1.isSameNode(div1)); // true
自定义元素节点
现代浏览器支持创建自定义元素:
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
border: 1px solid #ccc;
}
</style>
<slot></slot>
`;
}
}
customElements.define('my-element', MyElement);
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn