react动态创建菜单并实现局部刷新(使用react-virtualized实现图片动态高度长列表的问题)
类别:编程学习 浏览量:2606
时间:2022-03-29 03:45:06 react动态创建菜单并实现局部刷新
使用react-virtualized实现图片动态高度长列表的问题目录
- 开发中遇到的问题
- 解决方案
- 具体实现
- 实际效果
- 小结
虚拟列表是一种根据滚动容器元素的可视区域来渲染长列表数据中某一个部分数据的技术。虚拟列表是对长列表场景一种常见的优化,毕竟很少有人在列表中渲染上百个子元素,只需要在滚动条横向或纵向滚动时将可视区域内的元素渲染出即可。
开发中遇到的问题1.长列表中的图片要保持原图片相同的比例,那纵向滚动在宽度不变的情况下,每张图片的高度就是动态的,当该列表项高度发生了变化,会影响该列表项及其之后所有列表项的位置信息。
2.图片width,height必须在图片加载完成后才能获得.
解决方案我们使用react-virtualized中list组件,官方给出的例子
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 ( <li key={key} style={style}> {list[index]} </li> ); } // Render your list ReactDOM.render( <List width={300} height={300} rowCount={list.length} rowHeight={20} rowRenderer={rowRenderer} />, document.getElementById('example'), );
其中rowHeight是每一行的高度,可以传入固定高度也可以传入function。每次子元素高度改变需要调用recomputeRowHeights方法,指定索引后重新计算行高度和偏移量。
具体实现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} /> }
先写一个获取图片高度的组件,通过定时循环检测获取并计算出高度传给父组件。
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 ( <li key={key} style={style}> <img src={list[index].imgUrl} alt='' style={{width: '100%'}}/> </li> ) } return ( <li key={key} style={style}> <ImgHeightComponent imgUrl={list[index].imgUrl} width={autoWidth} height={autoHeight} onHeightReady={(height) => { this.handleHeightReady(height, index) }} /> </li> ) } render() { const { list } = this.state return ( <> <li 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> </li> </> ) } }
父组件通过handleHeightReady方法收集所有图片的高度,并在每一次高度改变调用List组件的recomputeRowHeights方法通知组件重新计算高度和偏移。到这里基本已经解决遇到的问题。
实际效果 小结目前只是使用react-virtualized来完成图片长列表实现,具体react-virtualized内部实现还需要进一步研究。
以上就是用react-virtualized实现图片动态高度长列表的详细内容,更多关于react virtualized长列表的资料请关注开心学习网其它相关文章!
您可能感兴趣
- react 封装下拉选择框(React鼠标多选功能的配置方法)
- react怎么使用父组件(关于antd tree和父子组件之间的传值问题react 总结)
- html5创作(HTML5录音实践总结Preact)
- reactnative示例代码(React Native项目框架搭建的一些心得体会)
- vue3.0 如何使用useroute(详解vue3中setUp和reactive函数的用法)
- react的动画实现(React实现动效弹窗组件)
- react重点和难点(关于React状态管理的三个规则总结)
- vue3 props用法(vue3组合API中setup、 ref、reactive的使用大全)
- react native web白屏(关于React Native 无法链接模拟器的问题)
- react自适应布局如何实现(React实现分页效果)
- react高阶组件怎么用(React 高阶组件HOC用法归纳)
- react定时任务(手把手带你用React撸一个日程组件)
- react代码质量检查(react如何实现一个密码强度检测器详解)
- react常见问题(React编程中需要注意的两个错误)
- react怎么添加动态html(react中的DOM操作实现)
- linux虚拟内存实现需要哪六种机制(解析Linux高性能网络IO和Reactor模型)
- 一个30岁男人外遇失败的全过程(一个30岁男人外遇失败的全过程)
- 《无敌破坏王2》 不聊彩蛋,聊聊我从动画里看到的现实那些事儿(无敌破坏王2不聊彩蛋)
- 《寄生虫》 三观不正 人类悲欢从来不相通,感同身受也并非本能(寄生虫三观不正)
- 这部动漫中的女孩子,可比101女孩更加励志(这部动漫中的女孩子)
- 《白狐的人生》热拍 贾征宇偶像包袱难自弃 图(白狐的人生热拍)
- 七夕取消了,牛郎织女没做核酸七夕已经取消(牛郎织女没做核酸七夕已经取消)
热门推荐
- laravel自定义使用方法(Laravel使用Queue队列的技巧汇总)
- 腾讯云如何添加安全通信端口(腾讯云服务器如何添加安全通信端口?)
- mysql优化使用方法(详解Mysql函数调用优化)
- thinkphp支付宝支付(thinkPHP和onethink微信支付插件分享)
- thinkphp快速入门手册(从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解)
- nginx配置两个前端web服务(你真的了解如何将Nginx配置为Web服务器吗)
- js编写一个数组去重的方法(JS实现数组过滤从简单到多条件筛选)
- Asp.net导出Excel乱码
- python豆瓣电影爬虫课程设计报告(详解python 模拟豆瓣登录豆瓣6.0)
- 宝塔面板程序目录(将宝塔面板linux版装在/www以外的目录的方法)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9