Virtual list is a technology that renders a portion of the data in a long list according to the visible area of the scroll container element. Virtual lists are a common optimization for long list scenarios. After all, few people render hundreds of sub-elements in a list. It is only necessary to render the elements in the visible area when the scroll bar scrolls horizontally or vertically. Problems encountered during development1. The pictures in the long list should maintain the same proportion as the original pictures. When the width remains unchanged during vertical scrolling, the height of each picture is dynamic. When the height of the list item changes, it will affect the position information of the list item and all subsequent list items. 2. The image width and height can only be obtained after the image is loaded. SolutionWe use the list component in react-virtualized, the official example 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'), ); Where rowHeight is the height of each row. You can pass in a fixed height or a function. Each time the height of a child element changes, the recomputeRowHeights method needs to be called to recalculate the row height and offset after specifying the index. Specific implementationconst 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() // Change the src of the image img.src = url let set = null const onload = () => { if (img.width || img.height) { //Image loading completed 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} /> } First, write a component to obtain the image height, obtain and calculate the height through a timed loop detection and pass it to the parent component. 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> </> ) } } The parent component collects the heights of all images through the handleHeightReady method, and calls the recomputeRowHeights method of the List component every time the height changes to notify the component to recalculate the height and offset. At this point, the problems encountered have basically been solved. Actual Results summaryCurrently, we only use react-virtualized to implement the long list of images. The specific internal implementation of react-virtualized needs further study. The above is the details of using react-virtualized to implement a long list of dynamic images. For more information about react virtualized long lists, please pay attention to other related articles on 123WORDPRESS.COM! You may also be interested in:
|
<<: Tutorial on installing php5, uninstalling php, and installing php7 on centos
>>: How to create a new user in CentOS and enable key login
The Docker container that has been running shows ...
<br />Web Design and Production Test Part I ...
Async Hooks is a new feature of Node8. It provide...
This article example shares the specific code of ...
Table of contents Preface Simulating data Merged ...
1. Download the mysql repo source $ wget http://r...
If a website is widescreen, you drag the browser ...
Sometimes, we need to use the hyperlink <a> ...
When developing mobile apps, you often encounter ...
1. Dynamic parameters Starting from 2.6.0, you ca...
1. Why is eject not recommended? 1. What changes ...
This article shares simple HTML and music player ...
<br />In the page, typesetting is achieved b...
After entering yum in linux, the prompt: -bash: /...
In fact, this is also a clickbait title, and it c...