怎样做自己的的社交网站,国家工商局网站官网,中国logo设计公司排名,梧州网页设计当浏览器遇到性能瓶颈导致页面卡顿时#xff0c;你会怎么处理#xff1f;如何查找问题的原因#xff1f;
浏览器本身自带性能检测工具#xff0c;通常我们分析由脚本导致的页面卡顿会选择 性能#xff08;performance#xff09; 选项卡#xff0c;在其中我们可以找到导…当浏览器遇到性能瓶颈导致页面卡顿时你会怎么处理如何查找问题的原因
浏览器本身自带性能检测工具通常我们分析由脚本导致的页面卡顿会选择 性能performance 选项卡在其中我们可以找到导致页面卡顿的函数另外通过观察我们可以看到脚本的执行时间占比以及页面卡顿的程度。 此外还有 内存 选项卡可以截取当前页面的内存快照由于我们的页面通常不像服务器那样一直运行所以平常我们也不会过于关注页面的内存使用问题。
1. 渲染大量数据
由于要渲染大量数据我们刚开始学习前端时如果经验不足就会简单地将所有数据全部一次性地渲染到页面上这样势必会造成页面的卡顿。所以这种方法我这里也不会去介绍。
下面直接进入正轨首先提出一个问题引发思考如果让你去实现你会怎么实现
1.1. 采用异步
我首先是想到如果要渲染大量数据我们可以将这一个巨大的任务拆分成一个个的小任务来执行将这一个个的小任务加入到任务队列当中采用异步的方式来慢慢地执行。
不过这个会有个缺陷由于这么多数据是按照顺序来依次执行的所以当用户想查看比较靠后的数据时用户会发现数据一直在加载中、一直在渲染然后用户等啊等最后点击关闭标签页。
下面是一个简单的使用异步实现的逻辑只包含部分代码
const ul document.querySelector(ul);let total 100_000_000;
let count 0;function loop() {const fragment document.createDocumentFragment();for (let i 0; i 20 count total; i, count) {const li document.createElement(li);li.textContent count;fragment.appendChild(li);}ul.appendChild(fragment);window.requestAnimationFrame(loop);
}loop();观察上面的代码其中使用到了 requestAnimationFrame 函数它接收一个函数作为参数这个函数会在浏览器每一帧渲染结束之后执行。
为什么不使用 setTimeout 定时器因为 setTimeout 函数无法控制函数的执行时机我们只知道函数会被加入到任务队列但并不知道函数会在何时执行而 requestAnimationFrame 函数则固定在每一帧渲染之后执行这样就不会在视觉上让用户感觉页面卡顿。
当然如果 requestAnimationFrame 的函数执行时间过长会推迟下一帧的渲染所以尽量不要将耗时任务放在其中。
1.2. 虚拟列表
虚拟列表采用的思想类似于懒加载都是只加载用户看得见的数据懒加载在计算机上随处可见比如单例模式中的饿汉式、图片的懒加载等在我们常用的 QQ 中像消息列表联系人列表他也采用了类似于虚拟列表的形式进行渲染以减少内存的使用量。
因为这里我们要处理大量数据的渲染如果要求所有的数据必须全部渲染在可视区当中那么懒加载就派不上用场了。
虚拟列表主要由可视区的数据构成其他的位置都是空白。我们可以通过 padding 或者是 top/left 来制造空白。如下图所示图片来自这篇文章 面试官如何一次性渲染十万条数据 - 掘金 (juejin.cn)可视区展示我们想看见的数据缓存区就是我说的空白。 实现的代码如下
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyle* {margin: 0;padding: 0;}.scroll-box {height: 100vh;overflow-y: scroll;}/style
/head
bodydiv classscroll-boxul/ul/divscript src./test.js/script
/body
/html对应的 test.js const ul document.querySelector(ul);
const scrollBox document.querySelector(.scroll-box);let total 100_000_000;
let count 0;
let liHeight 20;
// 要展示的数据量
let showCount scrollBox.clientHeight / liHeight 0;let totalHeight total * liHeight;function generateLi() {// 计算出来的处于可视区顶部的数据索引let index (scrollBox.scrollTop / liHeight) 0;const fragment document.createDocumentFragment();// 制造空白ul.style.paddingTop ${index * liHeight}px;ul.style.paddingBottom ${(totalHeight - (index 20) * liHeight)}px;// 生成可视区数据for (let i 0; i showCount; i) {const li document.createElement(li);li.textContent ${index i};fragment.appendChild(li);}// 重新设置元素这里元素并没有考虑复用ul.innerHTML ;ul.appendChild(fragment);
}generateLi();scrollBox.addEventListener(scroll, generateLi);多嘴一句当前元素可以滚动才有 scrollTop 值否则一直为 0。比如当前元素固定了高度但是它的子元素的高度超出了它的高度就会导致溢出这是我们可以设置 overflow-y: auto当前元素就会有滚动条。
而 scrollTop 就是当前元素的顶部与它的子元素的顶部的距离没有负值。
2. 参考
参考文献
面试官如何一次性渲染十万条数据 - 掘金 (juejin.cn)