如何使用react-virtualized实现图片动态高度长列表

小编给大家分享一下如何使用react-virtualized实现图片动态高度长列表,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

虚拟列表是一种根据滚动容器元素的可视区域来渲染长列表数据中某一个部分数据的技术。虚拟列表是对长列表场景一种常见的优化,毕竟很少有人在列表中渲染上百个子元素,只需要在滚动条横向或纵向滚动时将可视区域内的元素渲染出即可。

开发中遇到的问题

1.长列表中的图片要保持原图片相同的比例,那纵向滚动在宽度不变的情况下,每张图片的高度就是动态的,当该列表项高度发生了变化,会影响该列表项及其之后所有列表项的位置信息。

2.图片width,height必须在图片加载完成后才能获得.

解决方案

我们使用react-virtualized中list组件,官方给出的例子

importReactfrom'react';
importReactDOMfrom'react-dom';
import{List}from'react-virtualized';

//Listdataasanarrayofstrings
constlist=[
'BrianVaughn',
//Andsoon...
];

functionrowRenderer({
key,//Uniquekeywithinarrayofrows
index,//Indexofrowwithincollection
isScrolling,//TheListiscurrentlybeingscrolled
isVisible,//ThisrowisvisiblewithintheList(egitisnotanoverscannedrow)
style,//Styleobjecttobeappliedtorow(topositionit)
}){
return(

{list[index]}
); } //Renderyourlist ReactDOM.render( , document.getElementById('example'), );

其中rowHeight是每一行的高度,可以传入固定高度也可以传入function。每次子元素高度改变需要调用recomputeRowHeights方法,指定索引后重新计算行高度和偏移量。

具体实现

constImgHeightComponent=({imgUrl,onHeightReady,height,width})=>{
const[style,setStyle]=useState({
height,
width,
display:'block',
})
constgetImgWithAndHeight=(url)=>{
returnnewPromise((resolve,reject)=>{
varimg=newImage()
//改变图片的src
img.src=url
letset=null
constonload=()=>{
if(img.width||img.height){
//图片加载完成
clearInterval(set)
resolve({width:img.width,height:img.height})
}
}
set=setInterval(onload,40)
})
}

useEffect(()=>{
getImgWithAndHeight(imgUrl).then((size)=>{
constcurrentHeight=size.height*(width/size.width)
setStyle({
height:currentHeight,
width:width,
display:'block',
})
onHeightReady(currentHeight)
})
},[])
return
}

先写一个获取图片高度的组件,通过定时循环检测获取并计算出高度传给父组件。

importReact,{useState,useEffect,useRef}from'react'
importstylesfrom'./index.scss'
import{AutoSizer}from'react-virtualized/dist/commonjs/AutoSizer'
import{List}from'react-virtualized/dist/commonjs/List'

exportdefaultclassDocumentStudyextendsReact.Component{
constructor(props){
super(props)
this.state={
list:[],
heights:[],
autoWidth:900,
autoHeight:300
}
}

handleHeightReady=(height,index)=>{
this.setState(
(state)=>{
constflag=state.heights.some((item)=>item.index===index)
if(!flag){
return{
heights:[
...state.heights,
{
index,
height,
},
],
}
}
return{
heights:state.heights,
}
},
()=>{
this.listRef.recomputeRowHeights(index)
},
)
}

getRowHeight=({index})=>{
constrow=this.state.heights.find((item)=>item.index===index)
returnrow?row.height:this.state.autoHeight
}

renderItem=({index,key,style})=>{
const{list,autoWidth,autoHeight}=this.state
if(this.state.heights.find((item)=>item.index===index)){
return(


) } return( { this.handleHeightReady(height,index) }} />
) } render(){ const{list}=this.state return( <> {({width,height})=>( (this.listRef=ref)} width={width} height={height} overscanRowCount={10} rowCount={list.length} rowRenderer={this.renderItem} rowHeight={this.getRowHeight} /> )}
) } }

父组件通过handleHeightReady方法收集所有图片的高度,并在每一次高度改变调用List组件的recomputeRowHeights方法通知组件重新计算高度和偏移。到这里基本已经解决遇到的问题。

实际效果

目前只是使用react-virtualized来完成图片长列表实现,具体react-virtualized内部实现还需要进一步研究。

看完了这篇文章,相信你对“如何使用react-virtualized实现图片动态高度长列表”有了一定的了解,如果想了解更多相关知识,欢迎关注恰卡编程网行业资讯频道,感谢各位的阅读!

发布于 2021-05-30 14:05:36
分享
海报
158
上一篇:C#如何实现PDF签名时添加时间戳下一篇:Python怎么生成词云
目录

推荐阅读

忘记密码?

图形验证码