105-js-21-Dom

概述

DOM本质:一棵树
HTML和DOM的区别:HTML是文件或者说一段代码,DOM是浏览器内存中已经初始化好的一棵树,树的结构

获取 DOM 节点

getElementById

const div1 = document.getElementById('div1')

getElementsByTagName

const divList = document.getElementsByTagName('div') // 集合

getElementsByClassName

const containerList = document.getElementsByClassName('container') // 集合

querySelectorAll

const pList = document.querySelectorAll('p')

property 和 attribute

property:修改JS对象属性,不会体现到HTML结构中

attribute:修改HTML属性,会改变HTML 结构(标签结构)

两者都有可能引起DOM重新渲染

建议:尽量用 property 操作,因为property可能会在JS机制中,避免一些不必要的DOM渲染;但是attribute是修改HTML结构,一定会引起DOM结构的重新渲染,而DOM重新渲染是比较耗费性能的

const pList = document.querySelectorAll('p')
const p1 = pList[0]

// property 形式
p1.style.width = '100px'
console.log( p1.style.width )
p1.className = 'red'
console.log( p1.className )
console.log(p1.nodeName) // p
console.log(p1.nodeType) // 1

// attribute
p1.setAttribute('data-name', 'imooc')
console.log( p1.getAttribute('data-name') )
p1.setAttribute('style', 'font-size: 50px;')
console.log( p1.getAttribute('style') )

DOM结构操作

const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')

// 新建节点
const newP = document.createElement('p')
newP.innerHTML = 'this is newP'
// 插入节点
div1.appendChild(newP)

// 移动节点
const p1 = document.getElementById('p1')
div2.appendChild(p1)

// 获取父元素
console.log( p1.parentNode )

// 获取子元素列表
const div1ChildNodes = div1.childNodes
console.log( div1.childNodes )
const div1ChildNodesP = Array.prototype.slice.call(div1.childNodes).filter(child => {
    if (child.nodeType === 1) {
        return true
    }
    return false
})
console.log('div1ChildNodesP', div1ChildNodesP)

div1.removeChild( div1ChildNodesP[0] )

DOM操作性能优化

避免频繁的 DOM 操作

对 DOM 查询做缓存

// 不缓存 DOM 查询结果
for (let i = 0; i < document.getElementsByTagName('p').length; i++) {
  // 每次循环,都会计算length,频繁进行DOM查询
}

// 缓存 DOM 查询结果
const pList = document.getElementsByTagName('p')
const length = pList.length
for (let i = 0; i < length; i++) {
  // 缓存length,只进行一次DOM查询
}

将频繁操作改为一次性操作

const list = document.getElementById('list')
for (let i  = 0; i < 20; i++) {
    const li = document.createElement('li')
    li.innerHTML = `List item ${i}`
    list.appendChild(li)
}
const list = document.getElementById('list')

// 创建一个文档片段,此时还没有插入到 DOM 结构中
const frag = document.createDocumentFragment()

for (let i  = 0; i < 20; i++) {
    const li = document.createElement('li')
    li.innerHTML = `List item ${i}`

    // 先插入文档片段中
    frag.appendChild(li)
}

// 都完成之后,再统一插入到 DOM 结构中
list.appendChild(frag)

console.log(list)