高性能JavaScript之DOM编程的优化(一)

「这是我参与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的访问与修改 

  1. 减少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;
复制代码
  1. 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 及其更早版本。

Guess you like

Origin juejin.im/post/7062717393616764958