整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML DOM 节点介绍

OM 节点

根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:

整个文档是一个文档节点
每个 HTML 元素是元素节点
HTML 元素内的文本是文本节点
每个 HTML 属性是属性节点
注释是注释节点

HTML DOM 节点树

HTML DOM 将 HTML 文档视作树结构。这种结构被称为节点树:

HTML DOM Tree 实例


通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点。

节点父、子和同胞

节点树中的节点彼此拥有层级关系。

父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点。同级的子节点被称为同胞(兄弟或姐妹)。

在节点树中,顶端节点被称为根(root)
每个节点都有父节点、除了根(它没有父节点)
一个节点可拥有任意数量的子
同胞是拥有相同父节点的节点
下面的图片展示了节点树的一部分,以及节点之间的关系:


请看下面的 HTML 片段:

<html>
  <head>
    <title>DOM 教程</title>
  </head>
  <body>
    <h1>DOM 第一课</h1>
    <p>Hello world!</p>
  </body>
</html>
  • 从上面的 HTML 中:
  • <html> 节点没有父节点;它是根节点
  • <head> 和 <body> 的父节点是 <html> 节点
  • 文本节点 "Hello world!" 的父节点是 <p> 节点

并且:

  • <html> 节点拥有两个子节点:<head> 和 <body>
  • <head> 节点拥有一个子节点:<title> 节点
  • <title> 节点也拥有一个子节点:文本节点 "DOM 教程"
  • <h1> 和 <p> 节点是同胞节点,同时也是 <body> 的子节点

并且:

  • <head> 元素是 <html> 元素的首个子节点
  • <body> 元素是 <html> 元素的最后一个子节点
  • <h1> 元素是 <body> 元素的首个子节点
  • <p> 元素是 <body> 元素的最后一个子节点

警告!

DOM 处理中的常见错误是希望元素节点包含文本。

在本例中:<title>DOM 教程</title>,元素节点 <title>,包含值为 "DOM 教程" 的文本节点。

可通过节点的 innerHTML 属性来访问文本节点的值。


树是一种数据结构,由一组表示分层树结构的链接节点组成。每个节点都通过父子关系链接到其他节点。树中的第一个节点是根,而没有任何子节点的节点是叶子。

JavaScript 树可视化

树数据结构中的每个节点都必须具有以下属性:

key: 节点的键

value: 节点的值

parent: 节点的父节点(null如果没有)

children: 指向节点子节点的指针数组

树形数据结构的主要操作有:

insert: 插入一个节点作为给定父节点的子节点

remove: 从树中删除一个节点及其子节点

find: 检索给定节点

preOrderTraversal: 通过递归遍历每个节点及其子节点来遍历树

postOrderTraversal: 通过递归遍历每个节点的子节点来遍历树

class TreeNode {

constructor(key, value = key, parent = null) {

this.key = key;

this.value = value;

this.parent = parent;

this.children = [];

}


get isLeaf() {

return this.children.length === 0;

}


get hasChildren() {

return !this.isLeaf;

}

}


class Tree {

constructor(key, value = key) {

this.root = new TreeNode(key, value);

}


*preOrderTraversal(node = this.root) {

yield node;

if (node.children.length) {

for (let child of node.children) {

yield* this.preOrderTraversal(child);

}

}

}


*postOrderTraversal(node = this.root) {

if (node.children.length) {

for (let child of node.children) {

yield* this.postOrderTraversal(child);

}

}

yield node;

}


insert(parentNodeKey, key, value = key) {

for (let node of this.preOrderTraversal()) {

if (node.key === parentNodeKey) {

node.children.push(new TreeNode(key, value, node));

return true;

}

}

return false;

}


remove(key) {

for (let node of this.preOrderTraversal()) {

const filtered = node.children.filter(c => c.key !== key);

if (filtered.length !== node.children.length) {

node.children = filtered;

return true;

}

}

return false;

}


find(key) {

for (let node of this.preOrderTraversal()) {

if (node.key === key) return node;

}

return undefined;

}

}

用class创建一个类TreeNode,使用构造函数初始化 key, value, parent 和 children。

定义一个isLeaf getter方法,用Array.prototype.length检查children是否为空。

定义一个hasChildren getter方法,用来检查是否有子节点。

用 class 创建一个Tree,使用构造函数初始化树的根节点。

定义一个preOrderTraversal() 方法,按顺序遍历树的生成器方法,使用 yield* 语法将遍历委托给自身。

定义一个postOrderTraversal()方法,以后序遍历树的生成器方法,使用yield*语法将遍历委托给自身。

定义一个insert()方法,使用preOrderTraversal()和Array.prototype.push()方法向树中添加一个TreeNode 节点。

定义一个remove()方法,使用preOrderTraversal()和Array.prototype.filter()方法从树删除一个TreeNode节点。

定义一个find()方法,使用preOrderTraversal()方法检索树中的给定节点。

const tree = new Tree(1, 'AB');

tree.insert(1, 11, 'AC');

tree.insert(1, 12, 'BC');

tree.insert(12, 121, 'BG');

[...tree.preOrderTraversal()].map(x => x.value);

// ['AB', 'AC', 'BC', 'BCG']


tree.root.value; // 'AB'

tree.root.hasChildren; // true


tree.find(12).isLeaf; // false

tree.find(121).isLeaf; // true

tree.find(121).parent.value; // 'BC'


tree.remove(12);


[...tree.postOrderTraversal()].map(x => x.value);

// ['AC', 'AB']

过 HTML DOM,您能够使用节点关系在节点树中导航。


HTML DOM 节点列表

getElementsByTagName() 方法返回节点列表。节点列表是一个节点数组。

下面的代码选取文档中的所有 <p> 节点:

实例

varx=document.getElementsByTagName("p");

可以通过下标号访问这些节点。如需访问第二个 <p>,您可以这么写:

y=x[1];

尝试一下 »

注意:

下标号从 0 开始。


HTML DOM 节点列表长度

length 属性定义节点列表中节点的数量。

您可以使用 length 属性来循环节点列表:

实例

x=document.getElementsByTagName("p");for(i=0;i<x.length;i++){document.write(x[i].innerHTML); document.write("<br>");}

实例解析:

  • 获取所有 <p> 元素节点

  • 输出每个 <p> 元素的文本节点的值


导航节点关系

您能够使用三个节点属性:parentNode、firstChild 以及 lastChild ,在文档结构中进行导航。

请看下面的 HTML 片段:

<html><head><metacharset="utf-8"></head><body><p>Hello World!</p><div><p>DOM 是非常有用的!</p><p>这个实例演示了节点的关系。</p></div></body></html>

  • 首个 <p> 元素是 <body> 元素的首个子元素(firstChild)

  • <div> 元素是 <body> 元素的最后一个子元素(lastChild)

  • <body> 元素是首个 <p> 元素和 <div> 元素的父节点(parentNode)

firstChild 属性可用于访问元素的文本:

实例

<pid="intro">Hello World!</p><script>x=document.getElementById("intro");document.write(x.firstChild.nodeValue);</script>

尝试一下 »


DOM 根节点

这里有两个特殊的属性,可以访问全部文档:

  • document.documentElement - 全部文档

  • document.body - 文档的主体

实例

<p>Hello World!</p><div><p>DOM 是非常有用的!</p><p>这个实例演示了 <b>document.body</b> 属性。</p></div><script>alert(document.body.innerHTML);</script>

尝试一下 »


childNodes 和 nodeValue

除了 innerHTML 属性,您也可以使用 childNodes 和 nodeValue 属性来获取元素的内容。

下面的代码获取 id="intro" 的 <p> 元素的值:

实例

<pid="intro">Hello World!</p><script>txt=document.getElementById("intro").childNodes[0].nodeValue;document.write(txt);</script>

尝试一下 »

在上面的例子中,getElementById 是一个方法,而 childNodes 和 nodeValue 是属性。