用 JS 实现一个循环的动画
- 导致浏览器卡顿的原因一般都是操作 DOM 的次数太频繁。如果想要渲染很多条数据不造成卡顿,那么就一定要尽可能的减少操作 DOM 的次数。比方说 React 的虚拟 DOM,本质上就是用 JS 数据来模拟真实 DOM树,从而大大减少了操作真是 DOM 的次数。
// html
<div id="box"></div>
// css
#box {
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0;
zoom: 1;
}
定时器实现
- 因为大多数屏幕渲染的时间间隔是每秒60帧,所以时间间隔是1000/60
let box = document.getElementById("box");
let flag = true;
let left = 0;
let t = null;
function render() {
if (flag == true) {
if (left >= 100) {
flag = false;
}
box.style.left = ` ${left++}px`;
} else {
if (left <= 0) {
flag = true;
clearInterval(t);
}
box.style.left = ` ${left--}px`;
}
};
t = setInterval(function () {
render()
}, 1000 / 60);
requestAnimationFrame
- requestAnimationFrame 是由浏览器专门为动画提供的 API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了 CPU 开销。
let box = document.getElementById("box");
let flag = true;
let left = 0;
let t = null;
function render() {
if (flag == true) {
if (left >= 100) {
flag = false
}
box.style.left = ` ${left++}px`
} else {
if (left <= 0) {
flag = true
}
box.style.left = ` ${left--}px`
}
};
function animationLoop(time) {
render();
raf = requestAnimationFrame(animationLoop);
if (left < 0) {
cancelAnimationFrame(raf);
}
};
animationLoop();
渲染十万条数据
- 虚拟 DOM
- 分段渲染,先使用
document.createDocumentFragment()
创建文档碎片节点,再使用 requestAnimationFrame
逐帧渲染
let ul = document.querySelector('ul');
const total = 1000;
let raf;
// 分段渲染
const once = 20; // 一次渲染的条数
const loopCount = total / once; // 全部渲染完需要的次数
let countHasRender = 0; // 已经渲染的次数
let num = 0; // 渲染条数
function add() {
// 创建虚拟节点,使用 createDocumentFragment 不会触发渲染
const fragment = document.createDocumentFragment();
for (let i = 0; i < once; i++) {
const li = document.createElement('li');
li.innerText = num++;
fragment.appendChild(li);
};
ul.appendChild(fragment);
countHasRender++;
loop();
};
function loop() {
if (countHasRender < loopCount) {
raf = requestAnimationFrame(add);
} else {
cancelAnimationFrame(raf);
}
};
add();
网友评论