跳到主要内容

requestIdleCallback

2023年03月16日
柏拉文
越努力,越幸运

一、Circle 组件实现


import React, { useMemo } from "react";

function getColor() {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
return `rgba(${r},${g},${b},0.8)`;
}

function getPosition(position) {
const { width, height } = position;
return {
left: Math.ceil(Math.random() * width) + "px",
top: Math.ceil(Math.random() * height) + "px",
};
}

function Circle(props) {
const { position } = props;
const style = useMemo(() => {
return {
width: "10px",
height: "10px",
position: "absolute",
background: getColor(),
...getPosition(position),
};
});
return <div style={style} className="circle"></div>;
}

export default Circle;

二、App.tsx 组件实现


import React, { useState, useRef, useEffect, Fragment } from "react";
import ReactDOM from "react-dom";
import Circle from "./circle";

function App() {
const container = useRef(null);
const [dataList, setDataList] = useState([]);
const [renderList, setRenderList] = useState([]);
const [eachRenderNum, setEachRenderNum] = useState(500);
const [position, setPosition] = useState({ width: 0, height: 0 });

const renderNewList = (index) => {
const list = dataList.slice(
(index - 1) * eachRenderNum,
index * eachRenderNum
);
return (
<Fragment key={index}>
{list.map((item, index) => (
<Circle key={index} position={position} />
))}
</Fragment>
);
};

const toRenderList = (index, times) => {
if (index > times) {
return;
}
setRenderList(renderNewList(index));
requestIdleCallback(() => {
toRenderList(++index, times);
});
};

useEffect(() => {
const { offsetHeight, offsetWidth } = container.current;
const originList = new Array(20000).fill(1);

setPosition({ width: offsetWidth, height: offsetHeight });
setDataList(originList);
}, []);

useEffect(() => {
let index = 1;
const times = Math.ceil(dataList.length / eachRenderNum);
toRenderList(index, times);
}, [dataList]);

return (
<div
style={{ width: "500px", height: "500px", position: "relative" }}
ref={container}
>
{renderList}
</div>
);
}

ReactDOM.render(<App />, document.getElementById("root"));

参考资料


「前端进阶」高性能渲染十万条数据(时间分片)