本人已参与「新人创作礼」活动,一起开启掘金创作之路
日常开发中,我们经常遇见返回大量的数据,这个时候,如果一次性渲染会导致页面异常的卡顿,遇到这个情况,大部分人采取的应该都是分页的功能,输入获取到大量的数据,但是渲染的数据却只是一小部分,从而解决页面因渲染大量的dom而导致的卡顿
但是并不是所有情况都适合使用分页的功能,比如聊天信息,在获取聊天信息的时候,分页功能就不合适了,所有这个时候,应该采取虚拟dom的方法
虚拟dom个人认为就是渲染固定的几个dom,然后通过修改dom的内容,从而呈现出一种把全部数据渲染的假象,这样就可以减少浏览器的压力,从而不使页面卡顿
思路大致如下
首先获取到容器的高度,并且给容器添加scroll事件,
确定每一行的高度,然后判断出铺满容器需要多少个,
同时需要在容器的子元素(也就是每一行的父元素的兄弟元素)设置高度
这个高度是假象为全部数据渲染后的高度,用来撑起容器的,从而使滚动条可以滚动
代码如下
const [dd,setDd]=React.useState<any>([])
const [xr,setXr]=React.useState<any>([])
const boox=React.useRef(null)
const shuji=React.useRef({
height:0,
linheight:65,//每一行的高度,包括margin
xrnumber:0,
hcnumber:8,//以防出现空白的,多渲染
})
React.useEffect(()=>{
const {offsetHeight}=boox.current!
const {hcnumber,linheight}=shuji.current
let xrnumber=Math.ceil(offsetHeight/linheight)+hcnumber//渲染出来的dom个数
shuji.current={height:offsetHeight,xrnumber,hcnumber,linheight}
const d=new Array(1000).fill(1).map((item,index)=> index + 1 )
let boxw:any=document.querySelector('.boox_w')
boxw.style.height=d.length*linheight+'px'//撑起容器的dom高度
setXr(d.slice(0,xrnumber))
setDd(d)
},[])
return (
<div className='boox' ref={boox} >
<div className='boox_q' style={{height:shuji.current.height}} onScroll={(e)=>{
let dom:any=e.target
let d:any=document.querySelector('.boox_e')
let sco=dom.scrollTop-(dom.scrollTop%65)//注意这里是使用%,每一次偏差都不会超过65
d.style.transform = `translate3d(0, ${sco}px, 0)`//假象,看起来像滚动
setXr(dd.slice(Math.floor(dom.scrollTop/65),Math.floor(dom.scrollTop/65)+shuji.current.xrnumber))
}}>
<div className='boox_w'></div>
<div className='boox_e'>
{xr.map((T:any,I:any)=><div className='boox_r' key={I}>{T}</div>)}
</div>
</div>
</div>
)
css如下
.boox{
position: relative;
left:0;
top:60px;
// overflow: hidden;
bottom:0;
right: 0;
width: 500px;
height: 500px;
.boox_q{
overflow-y: scroll;
position: absolute;
width: 100%;
.boox_w{
position: absolute;
left:0;
top:0;
right: 0;
}
.boox_e{
.boox_r{
width: 100%;
height: 60px;
margin-top: 5px !important;
border-radius: 5px;
background-color: red;
color: white;
font-size: 20px;
}
}
}
}
修改图如下