理解DOM
Node类型
JavaScript中的所有类型的节点类型(12种)都继承自Node类型,所有节点类型(nodeType)都共享着相同的基本属性和方法
节点关系
大部分节点都childNodes
属性,其中保存这一个 NodeList对象
📌 NodeList对象是一个类数组对象,用于保存一组有序的节点,可以通过位置访问这些节点,大多数情况下NodeList是实时集合,是动态的,但是 parentNode.querySelector()
返回的NodeList是静态的
操作节点
节点类型(nodeType)
Document 类型
表示文档
💡 常见应用是作为HTMLDocument实例的document对象
(HTMLDcument继承自Document类型)
Element类型
用于表现XML或HTML元素
💡所有HTML元素都由HTMLElement类型或者它的子类型表示
var el = document.createElement('div')
el.className = 'message'
document.body.appendChild(el)
Text类型
表示文本节点,可以包含转义后的HTML字符,但不能包含HTML代码
💡 操作文本节点
可以通过nodeValue
属性或data
属性访问文本节点包含的文本,这两个属性包含的值相同,对nodeValue的修改也会通过data反映出来,反之亦然。
操作方法:
💡 创建文本节点
document.createTextNode(),接收一个参数—要插入节点中的文本
var textNode = document.createTextNode('hello')
DocumentFragment 类型
文档片段,在文档中没有对应的标记,可以包含和控制节点,但不会向文档那样占用额外的资源
文档片段不能直接添加到文档,可以将它作为一个“仓库”使用,在里面保存将来可能会添加到文档中的节点
如下所示,如果想向指定 ul 元素内添加三个li标签,逐个添加会导致浏览器反复渲染,为了避免就可以采用文档片段保存要创建的列表项,然后一次性添加
<ul id="list"></ul>
// 创建文档片段
var fragment = document.createDocumentFragment()
var ul = document.getElementById('list')
var li = null
for(var i=0; i < 3; i++) {
li = document.createElement('li')
li.appendChild(document.createTextNode('Item' + (i+1)))
fragment.appendChild(li)
}
ul.appendChild(fragment)
Attr类型
元素的特性在DOM中以Attr类型来表示,特性就是存在于元素attributes属性中的节点,但是尽管属于节点,但却不认为是DOM文档树的一部分
不建议使用attributes属性访问特性,使用以下操作方法更为方便
- getAttribute()
- setAttribute()
- removeAttribute()
使用document.createAttribute()并传入特性的名称可以创建新的特性节点
// 创建元素节点并传入标签名称
var el = document.createElement('div')
// 创建特性节点,并传入特性名称
var attr = document.createAttribute('self')
// 给特性赋值
attr.value = 'tip'
// 将特性节点插入元素节点
el.setAttributeNode(attr)
// 读取元素特性节点
el.attributes['self'].value // "tip"
el.getAttributeNode('self').value // tip
el.getAttribute('self') // 👉 "tip"
📌拓展:NodeList、NamedNodeMap、HTMLCollection
NodeList
表示节点的集合NamedNodeMap
表示属性节点 Attr 对象的集合HTMLCollection
表示包含了指定元素的集合
这三个集合都是动态的,每当文档结构发生变化时,它们都会得到更新,因此它们始终保存着最新最准确的信息。
下列代码会导致无限循环
let divs = document.getElementsByTagName('div')
// 取得文档中所有元素<div>元素的 HTMLCoolection,是动态的
let i
let div
// 每循环一次新增一个div,所有divs.length每循环一次都会新增1
// 这样 i 就永远不能打破循环条件
for ( i=0; i < divs.length; i++) {
div = document.createElement('div')
document.body.appendChild(div)
}
改进:使用NodeList的属性length初始化第二个变量
let divs = document.getElementsByTagName('div')
let len // 新增
let i
let div
for (i=0; i < len; i++) {
div = document.createElement('div')
document.body.appendChild(div)
}