2023年 4月 23日 来源: 新华社微博 字号:默认 超大

🌈本系列文章是博主精心整理的面试热点问题,吸收了大量的技术博客与面试文章,总结多年的面试经历,带你快速建立前端面试知识体系。抓住每一场面试的机会,知己知彼才能百战百胜。直击技术痛点,主动出击,精密打击,这才是面试拿到高薪的秘诀!

介绍

本章介绍 DOM 操作的知识点和题目。包括 DOM 结构,常用 DOM 操作,DOM 性能优化等。DOM 是网页结构的基础,学会 DOM 操作才可以做网页开发。

主要内容

JS Web API

背景

JS 基础知识,规定语法(ECMA 262 标准)
JS Web API,网页操作的 API(W3C 标准)
前者是后者的基础,两者结合才能真正实际应用

内容

DOM的本质

DOM,document object model
DOM的本质是从HTML中解析出来的一棵树,DOM结构就是树结构。

DOM节点操作

DOM节点操作:
获取dom节点:
documen.getElementById()
document.getElementsByClassName
document.getElementsByTagName
docuement.querySelectorAll  // css选择器
attribute // 对html属性进行修改
property  // js操作属性的一种形式   对dom元素的js变量进行修改
const plist = document.querySelectorAll('p')
const p1 = plist[0]
p1.className // 返回元素的类名
p1.nodeName // 返回节点名称
p1.nodeType // 返回节点类型  一般元素返回的1

attributeproperty的区别

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

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)
获取子元素列表,获取父元素
const div1ChildNodes = div1.childNodes
cosnole.log(div1.childNodes)
const div1ChildNodesP= Array.prototype.slice.call(div1.childNodes).filter(child => {//过滤
if(child.nodeType === 1) {//获得正常DOM节点。而不是text节点
return true
}
return false
})
cosnole.log('div1ChildNodesP',div1ChildNodesP)
console.log(p1.parentNode)
删除子元素
div1.removeChild(div1ChildNodesP[0])

如何优化 DOM 操作的性能

DOM 性能 DOM 操作会占用CPU,可能会导致浏览器的重绘和重排,使得运行耗时或者说耗费CPU计算比较多,频繁操作可能会导致卡顿的一些问题

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

一文搞懂JS-Web-API——DOM

2.将频繁操作改成一次性操作

const listNode = document.getElementById('list');
// 频繁操作
for(let i = 0, i < 10, i++) {
    const li = document.createElement('li');
    li.innerHTML = 'List item' + x;
    listNode.appendChild(li);
}
// 频繁操作改为一次性操作
// 创建一个文档片段,此时还没有插入到 DOM 树中 (理解为创建了一个虚拟DOM的teamplate元素)
const frag = document.createDocumentFragment();
for(let i = 0, i < 10, i++) {
    const li = document.createElement('li');
    li.innerHTML = 'List item' + x;
    frag.appendChild(li); // 将生成的 li 先插入到 虚拟DOM中
}
// 都完成之后,再插入到 DOM 树中
list.appendChild(frag);

一文搞懂JS-Web-API——DOM

下期介绍js的高级用法