理解DOM

DOM可以将任何HTML或XML文档描绘成层次化的节点树

Node类型

JavaScript中的所有类型的节点类型(12种)都继承自Node类型,所有节点类型(nodeType)都共享着相同的基本属性和方法

节点关系

大部分节点都childNodes属性,其中保存这一个 NodeList对象
📌 NodeList对象是一个类数组对象,用于保存一组有序的节点,可以通过位置访问这些节点,大多数情况下NodeList是实时集合,是动态的,但是 parentNode.querySelector()返回的NodeList是静态的

操作节点

节点类型(nodeType)

Document 类型

表示文档
image.png
💡 常见应用是作为HTMLDocument实例的document对象(HTMLDcument继承自Document类型)
image.png

Element类型

用于表现XML或HTML元素
image.png
💡所有HTML元素都由HTMLElement类型或者它的子类型表示
image.png

  1. var el = document.createElement('div')
  2. el.className = 'message'
  3. document.body.appendChild(el)

Text类型

表示文本节点,可以包含转义后的HTML字符,但不能包含HTML代码
image.png
💡 操作文本节点
可以通过nodeValue属性或data属性访问文本节点包含的文本,这两个属性包含的值相同,对nodeValue的修改也会通过data反映出来,反之亦然。
操作方法:
image.png
💡 创建文本节点
document.createTextNode(),接收一个参数—要插入节点中的文本

  1. var textNode = document.createTextNode('hello')

DocumentFragment 类型

文档片段,在文档中没有对应的标记,可以包含和控制节点,但不会向文档那样占用额外的资源
image.png
文档片段不能直接添加到文档,可以将它作为一个“仓库”使用,在里面保存将来可能会添加到文档中的节点
如下所示,如果想向指定 ul 元素内添加三个li标签,逐个添加会导致浏览器反复渲染,为了避免就可以采用文档片段保存要创建的列表项,然后一次性添加

  1. <ul id="list"></ul>
  2. // 创建文档片段
  3. var fragment = document.createDocumentFragment()
  4. var ul = document.getElementById('list')
  5. var li = null
  6. for(var i=0; i < 3; i++) {
  7. li = document.createElement('li')
  8. li.appendChild(document.createTextNode('Item' + (i+1)))
  9. fragment.appendChild(li)
  10. }
  11. ul.appendChild(fragment)

Attr类型

元素的特性在DOM中以Attr类型来表示,特性就是存在于元素attributes属性中的节点,但是尽管属于节点,但却不认为是DOM文档树的一部分
image.png

不建议使用attributes属性访问特性,使用以下操作方法更为方便

  • getAttribute()
  • setAttribute()
  • removeAttribute()

使用document.createAttribute()并传入特性的名称可以创建新的特性节点

  1. // 创建元素节点并传入标签名称
  2. var el = document.createElement('div')
  3. // 创建特性节点,并传入特性名称
  4. var attr = document.createAttribute('self')
  5. // 给特性赋值
  6. attr.value = 'tip'
  7. // 将特性节点插入元素节点
  8. el.setAttributeNode(attr)
  9. // 读取元素特性节点
  10. el.attributes['self'].value // "tip"
  11. el.getAttributeNode('self').value // tip
  12. el.getAttribute('self') // 👉 "tip"

📌拓展:NodeList、NamedNodeMap、HTMLCollection

  • NodeList 表示节点的集合
  • NamedNodeMap 表示属性节点 Attr 对象的集合
  • HTMLCollection 表示包含了指定元素的集合

这三个集合都是动态的,每当文档结构发生变化时,它们都会得到更新,因此它们始终保存着最新最准确的信息。
下列代码会导致无限循环

  1. let divs = document.getElementsByTagName('div')
  2. // 取得文档中所有元素<div>元素的 HTMLCoolection,是动态的
  3. let i
  4. let div
  5. // 每循环一次新增一个div,所有divs.length每循环一次都会新增1
  6. // 这样 i 就永远不能打破循环条件
  7. for ( i=0; i < divs.length; i++) {
  8. div = document.createElement('div')
  9. document.body.appendChild(div)
  10. }

改进:使用NodeList的属性length初始化第二个变量

  1. let divs = document.getElementsByTagName('div')
  2. let len // 新增
  3. let i
  4. let div
  5. for (i=0; i < len; i++) {
  6. div = document.createElement('div')
  7. document.body.appendChild(div)
  8. }