DOM节点操作
prototype 和 attribute 的区别
- prototype:修改对象属性,不会体现到 html 结构中
- attribute:修改 html 属性,会改变 html 结构
- 两者都有可能引起 DOM 重新渲染
const pList = document.querySelectorAll('p')
const p1 = pList[0]
// prototype
p1.style.width = '100px'
console.log(p1.style.width);
p1.className = 'red'
console.log(p1.className);
console.log(p1.nodeName);
console.log(p1.nodeType);
// attribute
p1.setAttribute('data-name','imooc')
console.log(p1.getAttribute('data-name'));
p1.setAttribute('style','font-size: 50px')
console.log(p1.getAttribute('style'));
DOM结构操作
常见的DOM结构操作有 新建节点( createElement() )、删除节点( 父元素.removeChild() )、插入节点/移动节点 ( appendChild() ) 、 获取父节点 ( 子元素.parentNode() ) 、 获取子元素( 父元素.ChildNodes() )
// dom结构操作
const div0 = document.getElementById('div0')
const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')
// 新建节点
const newP = document.createElement('p')
newP.innerHTML = 'this is p'
//插入节点
div1.appendChild(newP)
// 移动节点 -- 对已有节点用appendChild(),会将该节点移动,该节点原位置就会出现连续两个#text 父元素.childNodes
const p1 = document.getElementById('p1')
div2.appendChild(p1);
// 获取父元素
console.log(p1.parentNode);
// 获取子元素列表
console.log( div0.childNodes );
const div0ChildNode = div0.childNodes
// 筛选nodeType为1的子节点
const div0ChildNodeP = Array.prototype.slice.call(div0.childNodes).filter(child => {
if(child.nodeType === 1) {
return true
}
return false
})
console.log(div0ChildNodeP);
//删除子节点
div2.removeChild(p1)
console.log(div2.childNodes);
DOM性能
- DOM操作非常"昂贵",避免频繁的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 < 10; i++) {
const li = document.createElement('li')
li.innerHTML = `list item ${i}`
list.appendChild(li)
}
// 将频发操作改为一次性操作
// 创建一个文档片段,此时还没有插入到 DOM 树,不会影响性能
const frag = document.createDocumentFragment()
// 执行插入
for(let x = 0; x < 10; x++) {
const li = document.createElement('li')
li.innerHTML = `list item ${x}`
frag.appendChild(li)
}
// 都完成后,在插入到 DOM 树中
list.appendChild(frag)