「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
无论是用vue构建前端项目的今天,还是开发小程序,我们依旧离不开对dom的操作
严格的 MVVM 要求 View 不能和 Model 直接通信,而 Vue 提供了$refs 这个属性,让 Model 可以直接操作 View,违反了这一规定,所以说 Vue 没有完全遵循 MVVM。
但是频繁的操作dom,始终带来浏览器不小的消耗;也是富web应用中的最常见的性能瓶颈;
浏览器中的DOM
定义
DOM
(document Object Model) 文档对象模型,是html和xml文档的编程接口,由多层节点构成的文档,通过它,开发者可以对DOM进行操作,添加、删除以及修改。
为什么慢
一般来说,两个相互独立的功能只要通过接口彼此连接 ,就会产生消耗,
DOM和JavaScript比喻成两个岛屿,通过JavaScript访问DOM,就需要经过这座桥,频繁的访问DOM,过桥的次数就会多了起来,开销自然也多了起来;
所以我们需要合适的方法提升页面的交互相应速度,减少相应的开销成本
DOM的访问与修改
- 减少dom的访问次数
for (let i = 1; i <= 1000; ++i) {
document.getElementById('bookMarkDiv').innerHTML += "<li class='li'>" +文本 +"</li>"
}
复制代码
每次循环的时候,都会读取一次innerHTML属性值以及修改它
所以我们需要一次性修改即可,用局部变量进行存储修改的innerHTML
let txt = '';
for (let i = 1; i <= 1000; ++i) {
txt += "<li class='li'>" +文本 +"</li>"
}
document.getElementById('bookMarkDiv').innerHTML = txt;
复制代码
- HTML集合
HTML集合包含了DOM节点引用的类数组对象,它是类似数组的列表,所以它有length属性,但是没有数组的方法(push等)
const divArry = document.getElementByTagName('div');
for (let i = 1; i <= divArry.length; ++i) {
}
复制代码
我们可以将这个集合的长度存到局部变量中
const len = divArry.length;
复制代码
或者将这个集合复制到新数组中去。
const arr = toArray(divArry);
复制代码
多次访问集合元素使用局部变量
const naturalWidth = document.querySelector(`#img${fileId}`).naturalWidth
const naturalHeight = document.querySelector(`#img${fileId}`).naturalHeight
复制代码
上面例子中,访问了两次DOM元素只为了拿到该dom元素的两个属性,有可能会更多,这里我们优化
const imgDom = document.querySelector(`#img${fileId}`);
const naturalWidth = imgDom.naturalWidth
const naturalHeight = imgDom.naturalHeight
复制代码
遍历DOM
获取dom
从某一个dom元素开始,操作周围的元素时,或者递归查找所有子节点,推荐使用childNodes或者nextSibling获取每个相邻元素
function testChildNodes() {
const el = document.getElementById('content_left');
const ch = el.childNodes;
const len = ch.length;
let name = '';
for (let count = 0; count < len; count += 1) {
name += ch[count].nodeName;
}
return name;
}
testChildNodes()
复制代码
元素节点
推荐使用children,比childNode会快点
选择器
原生JS的选择器有
- getElementById:根据指定元素的id属性返回元素
- getElementsByName:返回所有指定name属性的元素
- getElementsByTagName:返回所有指定标签的元素
推荐使用querySelectorAll() 根据选择器规则返回所有符合要求的元素
或
querySelector() 获取到第一个匹配的节点
注意: querySelectorAll() 不适用于 Internet Explorer 8 及其更早版本。