您好,登錄后才能下訂單哦!
小編給大家分享一下如何使用react-virtualized實(shí)現(xiàn)圖片動態(tài)高度長列表,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
虛擬列表是一種根據(jù)滾動容器元素的可視區(qū)域來渲染長列表數(shù)據(jù)中某一個部分?jǐn)?shù)據(jù)的技術(shù)。虛擬列表是對長列表場景一種常見的優(yōu)化,畢竟很少有人在列表中渲染上百個子元素,只需要在滾動條橫向或縱向滾動時將可視區(qū)域內(nèi)的元素渲染出即可。
1.長列表中的圖片要保持原圖片相同的比例,那縱向滾動在寬度不變的情況下,每張圖片的高度就是動態(tài)的,當(dāng)該列表項(xiàng)高度發(fā)生了變化,會影響該列表項(xiàng)及其之后所有列表項(xiàng)的位置信息。
2.圖片width,height必須在圖片加載完成后才能獲得.
我們使用react-virtualized中l(wèi)ist組件,官方給出的例子
import React from 'react'; import ReactDOM from 'react-dom'; import {List} from 'react-virtualized'; // List data as an array of strings const list = [ 'Brian Vaughn', // And so on... ]; function rowRenderer({ key, // Unique key within array of rows index, // Index of row within collection isScrolling, // The List is currently being scrolled isVisible, // This row is visible within the List (eg it is not an overscanned row) style, // Style object to be applied to row (to position it) }) { return ( <div key={key} style={style}> {list[index]} </div> ); } // Render your list ReactDOM.render( <List width={300} height={300} rowCount={list.length} rowHeight={20} rowRenderer={rowRenderer} />, document.getElementById('example'), );
其中rowHeight是每一行的高度,可以傳入固定高度也可以傳入function。每次子元素高度改變需要調(diào)用recomputeRowHeights方法,指定索引后重新計(jì)算行高度和偏移量。
const ImgHeightComponent = ({ imgUrl, onHeightReady, height, width }) => { const [style, setStyle] = useState({ height, width, display: 'block', }) const getImgWithAndHeight = (url) => { return new Promise((resolve, reject) => { var img = new Image() // 改變圖片的src img.src = url let set = null const onload = () => { if (img.width || img.height) { //圖片加載完成 clearInterval(set) resolve({ width: img.width, height: img.height }) } } set = setInterval(onload, 40) }) } useEffect(() => { getImgWithAndHeight(imgUrl).then((size) => { const currentHeight = size.height * (width / size.width) setStyle({ height: currentHeight, width: width, display: 'block', }) onHeightReady(currentHeight) }) }, []) return <img src={imgUrl} alt='' style={style} /> }
先寫一個獲取圖片高度的組件,通過定時循環(huán)檢測獲取并計(jì)算出高度傳給父組件。
import React, { useState, useEffect, useRef } from 'react' import styles from './index.scss' import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer' import { List } from 'react-virtualized/dist/commonjs/List' export default class DocumentStudy extends React.Component { constructor(props) { super(props) this.state = { list: [], heights: [], autoWidth:900, autoHeight: 300 } } handleHeightReady = (height, index) => { this.setState( (state) => { const flag = 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 }) => { const row = this.state.heights.find((item) => item.index === index) return row ? 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 ( <div key={key} style={style}> <img src={list[index].imgUrl} alt='' style={{width: '100%'}}/> </div> ) } return ( <div key={key} style={style}> <ImgHeightComponent imgUrl={list[index].imgUrl} width={autoWidth} height={autoHeight} onHeightReady={(height) => { this.handleHeightReady(height, index) }} /> </div> ) } render() { const { list } = this.state return ( <> <div style={{ height: 1000 }}> <AutoSizer> {({ width, height }) => ( <List ref={(ref) => (this.listRef = ref)} width={width} height={height} overscanRowCount={10} rowCount={list.length} rowRenderer={this.renderItem} rowHeight={this.getRowHeight} /> )} </AutoSizer> </div> </> ) } }
父組件通過handleHeightReady方法收集所有圖片的高度,并在每一次高度改變調(diào)用List組件的recomputeRowHeights方法通知組件重新計(jì)算高度和偏移。到這里基本已經(jīng)解決遇到的問題。
目前只是使用react-virtualized來完成圖片長列表實(shí)現(xiàn),具體react-virtualized內(nèi)部實(shí)現(xiàn)還需要進(jìn)一步研究。
看完了這篇文章,相信你對“如何使用react-virtualized實(shí)現(xiàn)圖片動態(tài)高度長列表”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。