首页 > 其他分享 >如何高效操作DOM ?

如何高效操作DOM ?

时间:2024-09-02 10:50:32浏览次数:10  
标签:body 高效 console DOM 元素 耗时 let 操作

1. 为什么说 DOM 操作耗时

1.1 线程切换

  • 浏览器为了避免两个引擎同时修改页面而造成渲染结果不一致的情况,增加了另外一个机制,这两个引擎具有互斥性,也就是说在某个时刻只有一个引擎在运行,另一个引擎会被阻塞。操作系统在进行线程切换的时候需要保存上一个线程执行时的状态信息并读取下一个线程的状态信息,俗称上下文切换。而这个操作相对而言是比较耗时的
  • 每次 DOM 操作就会引发线程的上下文切换——从 JavaScript 引擎切换到渲染引擎执行对应操作,然后再切换回 JavaScript 引擎继续执行,这就带来了性能损耗。单次切换消耗的时间是非常少的,但是如果频繁地大量切换,那么就会产生性能问题

比如下面的测试代码,循环读取一百万次 DOM 中的 body 元素的耗时是读取 JSON 对象耗时的 10 倍。

// 测试次数:一百万次
const times = 1000000
// 缓存body元素
console.time('object')
let body = document.body
// 循环赋值对象作为对照参考
for(let i=0;i<times;i++) {
  let tmp = body
}
console.timeEnd('object')// object: 1.77197265625ms

console.time('dom')
// 循环读取body元素引发线程切换
for(let i=0;i<times;i++) {
  let tmp = document.body
}
console.timeEnd('dom')// dom: 18.302001953125ms

1.2 重新渲染

另一个更加耗时的因素是元素及样式变化引起的再次渲染,在渲染过程中最耗时的两个步骤为重排(Reflow)与重绘(Repaint)

浏览器在渲染页面时会将 HTML 和 CSS 分别解析成 DOM 树和 CSSOM 树,然后合并进行排布,再绘制成我们可见的页面。如果在操作 DOM 时涉及到元素、样式的修改,就会引起渲染引擎重新计算样式生成 CSSOM 树,同时还有可能触发对元素的重新排布和重新绘制

  • 可能会影响到其他元素排布的操作就会引起重排,继而引发重绘
    • 修改元素边距、大小
    • 添加、删除元素
    • 改变窗口大小
  • 引起重绘
    • 设置背景图片
    • 修改字体颜色
    • 改变 visibility属性值

了解更多关于重绘和重排的样式属性,可以参看这个网址:https://csstriggers.com/ (opens new window)

2. 如何高效操作 DOM

明白了 DOM 操作耗时之后,要提升性能就变得很简单了,反其道而行之,减少这些操作即可

2.1 在循环外操作元素

比如下面两段测试代码对比了读取 1000 次 JSON 对象以及访问 1000 次 body 元素的耗时差异,相差一个数量级

const times = 10000;
console.time('switch')
for (let i = 0; i < times; i++) {
  document.body === 1 ? console.log(1) : void 0;
}
console.timeEnd('switch') // 1.873046875ms
var body = JSON.stringify(document.body)
console.time('batch')
for (let i = 0; i < times; i++) {
  body === 1 ? console.log(1) : void 0;
}
console.timeEnd('batch') // 0.846923828125ms

2.2 批量操作元素

比如说要创建 1 万个 div 元素,在循环中直接创建再添加到父元素上耗时会非常多。如果采用字符串拼接的形式,先将 1 万个 div 元素的 html 字符串拼接成一个完整字符串,然后赋值给 body 元素的 innerHTML 属性就可以明显减少耗时

const times = 10000;
console.time('createElement')
for (let i = 0; i < times; i++) {
  const div = document.createElement('div')
  document.body.appendChild(div)
}
console.timeEnd('createElement')// 54.964111328125ms
console.time('innerHTML')
let html=''
for (let i = 0; i < times; i++) {
  html+='<div></div>'
}
document.body.innerHTML += html // 31.919921875ms
console.timeEnd('innerHTML')

标签:body,高效,console,DOM,元素,耗时,let,操作
From: https://blog.csdn.net/qq_45503196/article/details/141808776

相关文章

  • 操作符复习 看看你学会了吗?复习必备
    sizeof的应用判断输出值:#include<stdio.h>voidtest(intarr[]){   printf("%d\n",sizeofarr);}voidtry(charch[]){   printf("%d",sizeofch);}   intmain()   {      intarr[10]={0};      charch[10]={0}; ......
  • js 表格操作
    JS中的后代选择器表示选择某个元素的后代元素。后代元素是指某个元素内部的所有子元素、孙子元素、曾孙元素等。JS中的后代选择器可以通过以下两种方式实现:1.使用querySelectorAll()方法配合CSS选择器:varelements=document.querySelectorAll("父元素选择器后代元素选择器"......
  • [oeasy]python0032_ 火星文字幕_os_操作系统的作用_time_sleep_延迟
     032导入_import_os_time_延迟字幕效果_道德经文化_非主流火星文154播放·0赞同视频​ show:stepversion:1.0enable_checker:trueHelloWorld!回忆上次内容这次我们了解了unix系统在multics项目失败后汤普森和里奇为了玩游戏自制了u......
  • PW系列WiFi墨水屏标签操作指导
    设备初始化向厂家获取一下信息:服务器地址(MQTT地址)操作账号操作账号绑定的(产品KEY)WiFi标签管理系统登录WiFi标签管理系统:http://192.144.234.153:8000/index测试账户:user1080密码:123456(仅限于测试使用)我们提供云平台和V5基站两种方式1、云平台登录需要和客......
  • 如何通过 DOM 而不是通过表来呈现数据
    通过DOM(文档对象模型)呈现数据而不是通过表格,可以使用HTML的其他元素来组织和展示数据。以下是一些常见的方法:使用列表(<ul>或<ol>):将数据项作为列表项呈现,可以使用无序列表<ul>或有序列表<ol>。每个数据项可以是列表项<li>元素。使用段落(<p>):将每个数据项作为一个段落呈现,可......
  • Salt Function Flow:深度研发经验的沉淀,打造轻量级高效流程编排框架
    在开发者的世界里,业务流程编排是一个既复杂又关键的环节。如何高效地管理和编排这些流程,直接影响着系统的性能和可维护性。本次介绍一款基于大量研发实践经验而打造的流程编排框架——SaltFunctionFlow。它不仅轻量、强大,更是将多年实践中的最佳经验沉淀于其中,为开发者提......
  • 怎么在Windows操作系统部署阿里开源版通义千问(Qwen2)
    怎么在Windows操作系统部署阿里开源版通义千问(Qwen2) | 原创作者/编辑:凯哥Java              | 分类:人工智能学习系列教程GitHub上qwen2截图随着人工智能技术的不断进步,阿里巴巴通义千问团队近期发布了Qwen2系列开源模型,这一系列模型在多个领......
  • 怎么在Windows操作系统部署阿里开源版通义千问(Qwen2)
    怎么在Windows操作系统部署阿里开源版通义千问(Qwen2) | 原创作者/编辑:凯哥Java              | 分类:人工智能学习系列教程GitHub上qwen2截图随着人工智能技术的不断进步,阿里巴巴通义千问团队近期发布了Qwen2系列开源模型,这一系列模型在多个领域展......
  • PostgreSQL -- 使用 Mybatis 时对数据库的多个删除操作
     在Java中使用Mybatis与PostgreSQL数据库进行交互时,删除操作的语句根据不同的场景应用不同。 1.删除表内所有记录删除表内所有的记录。谨慎使用!<!--1.删除表内所有记录--><deleteid="deleteALl">deletefromtable_name;</delete>2......
  • Vue入门(四)Vue异步操作Axios
    一、Vue异步操作在Vue中发送异步请求,本质上还是AJAX。我们可以使用axios这个插件来简化操作!-使用步骤1.引入axios核心js文件。2.调用axios对象的方法来发起异步请求。3.调用axios对象的方法来处理响应的数据。-axios常用方法get:发起Get方式请求post:发起Po......