JS考题-你给我渲染一百万条数据(拿捏面试官版)

首先,当我们要同时渲染大量的数据,例如我用一个for循环去给一个节点增加十万条子项,并打印出时间如下:

js 复制代码
let start = new Date();
for (let i = 0; i < total; i++) {
  let li = document.createElement('li');
  li.innerText = i;
  ul.appendChild(li)
}
let end = new Date();
console.log(start-end)

但是这样打印时间是不对的,因为这打印出的只是主线程执行的时间,我们的页面还得进行渲染。

这是由于事件循环机制,页面渲染通常发生在微任务完成后。我们事件循环的机制是这样的(引导面试官问事件循环): 1.Script主线程 2.清空微任务队列 3.执行渲染 4.执行宏任务中的一个任务,并进入下一轮事件循环。

我们的渲染发生在主线程之后,所以我们应该在宏任务中完成定时。

js 复制代码
let start = new Date();
for (let i = 0; i < total; i++) {
  let li = document.createElement('li');
  li.innerText = i;
  ul.appendChild(li)
}
let end = new Date();
settimeout(() = > console.log(start-end),0)

我通过浏览器的performance工具(展示实力)查看之后发现,主要是页面的计算样式和渲染占据的时间长(引导面试官问渲染相关知识)。

造成了页面的卡顿,因为js交互为宏任务,无法继续循环。并且一次性渲染过多数据,页面渲染时间长。

因此我们采用分批次递归加入宏任务队列的方法,这样js事件也能从中间穿插,用户仍然能进行交互。

js 复制代码
        let ul = document.getElementById('container');
        let total = 100000;
        let once = 20;
        let times = Math.ceil(total / once);
        let index = 0;
        function render() {
            for (let i = 0; i < once; i++) {
                let li = document.createElement('li');
                li.innerText = 1;
                ul.appendChild(li);
            }
        }
        function loop() {
            setTimeout(() => {
                render();
                index++;
                if (index < times) {
                    loop();
                }
            }, 0); 
        }
        loop();

但是这时候还有问题,我们的浏览器刷新页面是60帧,也就是将近16.7ms每次,但是 某部分行为,例如查看滚动位置,(详情看我之前的文章事件循环)。这时候会立即的执行一次渲染。因为他要获取准确的计算结果。这种情况会造成大量的重排,就会引起卡顿。

这时候可以利用 嵌套 requestAnimationFrame 函数,避免中间渲染。提高浏览器的性能。 当嵌套 requestAnimationFrame 函数时候,他会在每帧前执行

或者我们也可以通过懒加载的方式,监听用户的onScreen事件来做到懒加载。

相关推荐
前端Hardy19 分钟前
HTML&CSS:3D图片切换效果
前端·javascript
spionbo40 分钟前
Vue 表情包输入组件实现代码及完整开发流程解析
前端·javascript·面试
全宝41 分钟前
✏️Canvas实现环形文字
前端·javascript·canvas
前端梭哈攻城狮1 小时前
uniapp图片上传添加水印/压缩/剪裁
前端·javascript·vue.js
天涯学馆1 小时前
前后端分离的 API 设计:技术深度剖析
前端·javascript·面试
爱编程的喵1 小时前
深入理解JavaScript原型机制:从Java到JS的面向对象编程之路
java·前端·javascript
独立开阀者_FwtCoder1 小时前
Cursor 1.0 重磅发来袭(毛骨悚然,开始学习你如何编码)
前端·javascript·github
五点六六六1 小时前
一些关于TreeShaking的AST的理解
前端·javascript·前端工程化
异常君2 小时前
Spring 中的 FactoryBean 与 BeanFactory:核心概念深度解析
java·spring·面试
海盐泡泡龟2 小时前
“组件、路由懒加载”,在 Vue3 和 React 中分别如何实现? (copy)
前端·javascript·react.js