JavaScript之操作DOM(上)

1. 概述

1.1 DOM

DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。

浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。

严格地说,DOM 不是 JavaScript 语法的一部分,但JavaScript 是最常用于 DOM 操作的语言,离开了 DOM,JavaScript 就无法控制网页。

1.2 节点(node)

DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。
节点的类型有七种,都继承了原生的节点对象 Node

1.3 节点树

文档的第一层只有一个节点,就是 HTML 网页的第一个标签 ,它构成了树结构的根节点(root node),其他 HTML 标签节点都是它的下级节点。
除了根节点,其他节点都有三种层级关系。

  • 父节点关系(parentNode):直接的那个上级节点
  • 子节点关系(childNodes):直接的下级节点
  • 同级节点关系(sibling):拥有同一个父节点的节点

2. Node 接口

所有 DOM 节点对象都继承了 Node 接口,拥有一些共同的属性和方法。

2.1 nodeType 属性

nodeType 属性返回一个整数值,表示节点的类型。
不同节点的 nodeType 属性值和对应的常量如下:

  • 元素节点(element):对应常量Node.ELEMENT_NODE,1
  • 属性节点(attr):常量Node.ATTRIBUTE_NODE,2
  • 文本节点(text):常量Node.TEXT_NODE,3
  • 注释节点(Comment):常量 Node.COMMENT_NODE,8
  • 文档节点(document):常量Node.DOCUMENT_NODE,9
  • 文档类型节点(DocumentType):常量Node.DOCUMENT_TYPE_NODE,10
  • 文档片断节点(DocumentFragment):常量Node.DOCUMENT_FRAGMENT_NODE,11

确定节点类型时,使用 nodeType 属性是常用方法。

2.2 nextSibling 属性

Node.nextSibling 属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回 null

// HTML 代码如下
// 
hello
world
var d1 = document.getElementById('d1'); var d2 = document.getElementById('d2'); d1.nextSibling === d2 // true

注意,该属性还包括文本节点和注释节点()。因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格。

2.3 previousSibling 属性

previousSibling 属性返回当前节点前面的、距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回 null

// HTML 代码如下
// 
hello
world
var d1 = document.getElementById('d1'); var d2 = document.getElementById('d2'); d2.previousSibling === d1 // true

注意,该属性还包括文本节点和注释节点。因此如果当前节点前面有空格,该属性会返回一个文本节点,内容为空格。

2.4 父节点 parentNode 和 parentElement 属性

  • parentNode 属性
    parentNode 属性返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)和文档片段节点(documentfragment)。
    文档节点(document)和文档片段节点(documentfragment)的父节点都是 null。另外,对于那些生成后还没插入 DOM 树的节点,父节点也是 null
  • parentElement 属性
    parentElement 属性返回当前节点的父元素节点。如果当前节点没有父节点,或者父节点类型不是元素节点,则返回 null

注意: Element:网页的各种HTML标签(比如 等)

2.5 childNodes 属性

childNodes 属性返回一个类似数组的对象(NodeList 集合),成员包括当前节点的所有子节点(包括文本节点和注释节点)。

var children = document.querySelector('ul').childNodes;

上面代码中,children 就是 ul 元素的所有子节点。

  • 另:关于 ParentNode.children
    如果当前节点是父节点,就会继承 ParentNode 接口。(只有元素节点(element)、文档节点(document)和文档片段节点(documentFragment)拥有子节点)
    children 属性返回一个 HTMLCollection 实例,成员是当前节点的所有元素子节点。
    注意,children 属性只包括元素子节点,不包括其他类型的子节点(比如文本子节点)

3. NodeList 接口

节点都是单个对象,有时需要一种数据结构,能够容纳多个节点。DOM 提供两种节点集合,用于容纳多个节点:NodeListHTMLCollection
主要区别是,NodeList 可以包含各种类型的节点,HTMLCollection 只能包含 HTML 元素节点。

3.1 NodeList 实例

通过以下方法可以得到 NodeList 实例。

  • Node.childNodes
  • document.querySelectorAll() 等节点搜索方法
document.body.childNodes instanceof NodeList // true

var children = document.body.childNodes;

Array.isArray(children) // false

children.length // 34
children.forEach(console.log)

上面代码中,NodeList实例 children 不是数组,但是具有 length 属性和 forEach 方法。

3.2 静态/动态集合

NodeList 实例可能是动态集合,也可能是静态集合。
所谓动态集合就是一个活的集合,DOM 删除或新增一个相关节点,都会立刻反映在 NodeList实例。
目前,只有 Node.childNodes 返回的是一个动态集合,其他的 NodeList 都是静态集合。

var children = document.body.childNodes;
children.length // 18
document.body.appendChild(document.createElement('p'));
children.length // 19

4. HTMLCollection 接口

4.1 概述

HTMLCollection 是一个节点对象的集合,只能包含元素节点(element),不能包含其他类型的节点。
它的返回值是一个类似数组的对象,但是与 NodeList 接口不同,HTMLCollection没有forEach 方法,只能使用 for 循环遍历。

HTMLCollection 实例都是动态集合,节点的变化会实时反映在集合中。

返回 HTMLCollection 实例的,主要是一些 Document对象的集合属性,比如 document.linksdocument.formsdocument.images等。

document.links instanceof HTMLCollection // true

4.2 id 或 name 属性引用

如果元素节点有 idname 属性,那么 HTMLCollection 实例上面,可以使用 id 属性或 name 属性引用该节点元素。如果没有对应的节点,则返回 null

// HTML 代码如下
// 

var pic = document.getElementById('pic');
document.images.pic === pic // true

上面代码中,document.images 是一个HTMLCollection实例,可以通过元素的 id 属性值,从 HTMLCollection 实例上取到这个元素。

5. ParentNode 接口

节点对象除了继承 Node 接口以外,还会继承其他接口。ParentNode 接口表示当前节点是一个父节点,提供一些处理子节点的方法。ChildNode 接口表示当前节点是一个子节点,提供一些相关方法。
(以下重复文字可看做为:重要的事情多说一遍)

5.1 父节点与 ParentNode 接口

如果当前节点是父节点,就会继承 ParentNode 接口。
由于只有元素节点(element)、文档节点(document)和文档片段节点(documentFragment)拥有子节点,因此只有这三类节点会继承 ParentNode 接口。

5.2 ParentNode.children(只读)

children 属性返回一个 HTMLCollection 实例,成员是当前节点的所有元素子节点。
注意,children 属性只包括元素子节点,不包括其他类型的子节点(比如文本子节点)。如果没有元素类型的子节点,返回值 HTMLCollection 实例的 length 属性为 0
另外,HTMLCollection 是动态集合,会实时反映 DOM 的任何变化。

6. ChildNode 接口

6.1 概述

ChildNode 接口表示当前节点是一个子节点,提供一些相关方法。
如果一个节点有父节点,那么该节点就继承了 ChildNode 接口。

6.2 方法

  • ChildNode.remove()
    remove 方法用于从父节点移除当前节点。
el.remove()

上面代码在 DOM 里面移除了 el 节点。

  • ChildNode.before()
    before 方法用于在当前节点的前面,插入一个或多个同级节点。两者拥有相同的父节点。
    该方法不仅可以插入元素节点,还可以插入文本节点。
var p = document.createElement('p');
var p1 = document.createElement('p');

// 插入元素节点
el.before(p);

// 插入文本节点
el.before('Hello');

// 插入多个元素节点
el.before(p, p1);

// 插入元素节点和文本节点
el.before(p, 'Hello');
  • ChildNode.after()
    after 方法用于在当前节点的后面,插入一个或多个同级节点,两者拥有相同的父节点。用法与before方法完全相同。

  • ChildNode.replaceWith()
    replaceWith 方法使用参数节点,替换当前节点。参数可以是元素节点,也可以是文本节点。

var span = document.createElement('span');
el.replaceWith(span);

上面代码中,el 节点将被 span 节点替换。

参考连接

  • 阮一峰, JavaScript 教程

你可能感兴趣的:(JavaScript之操作DOM(上))