多列表渲染(虚拟瀑布流)
多列表渲染(虚拟瀑布流)与虚拟列表原理一致,通过只渲染当前可视区域的视图,可以极大程度提升多列表渲染时的性能。注意:v3.6.10 及以下版本不支持。
示例
基础示例
在 React 或 Vue 等框架中,可以从 @tarojs/components-advanced 引入虚拟瀑布流(VirtualWaterfall)组件:
import { VirtualWaterfall } from '@tarojs/components-advanced'
一个最简单的长列表组件示例如下,其中 VirtualWaterfall 的 6 个属性都是必填项:
function buildData(offset = 0) {
return Array(100)
.fill(0)
.map((_, i) => i + offset)
}
const Row = React.memo(({ id, index, data }) => {
return (
<View id={id} className={index % 2 ? 'ListItemOdd' : 'ListItemEven'}>
Row {index} : {data[index]}
</View>
)
})
export default class Index extends Component {
state = {
data: buildData(0),
}
render() {
const { data } = this.state
const dataLen = data.length
return (
<VirtualWaterfall
height={800}
width="100%"
item={Row}
itemData={data}
itemCount={dataLen}
itemSize={100}
/>
)
}
}
无限滚动
实现无限滚动时,只需在列表滚动到底部时追加数据。以下示例展示了如何在滚动到底部时加载更多数据:
const Row = React.memo(({ id, index, data }) => {
return (
<View id={id} className={index % 2 ? 'ListItemOdd' : 'ListItemEven'}>
Row {index} : {data[index]}
</View>
)
})
function buildData(offset = 0) {
return Array(100)
.fill(0)
.map((_, i) => i + offset)
}
export default class Index extends Component {
state = {
data: buildData(0),
}
loading = false
listReachBottom() {
Taro.showLoading()
this.loading = true
setTimeout(() => {
const { data } = this.state
this.setState(
{
data: data.concat(buildData(data.length)),
},
() => {
this.loading = false
Taro.hideLoading()
}
)
}, 1000)
}
render() {
const { data } = this.state
const dataLen = data.length
const itemSize = 100
return (
<VirtualWaterfall
className="List"
height={500}
item={Row}
itemData={data}
itemCount={dataLen}
itemSize={itemSize}
width="100%"
onScroll={({ scrollDirection, scrollOffset }) => {
if (
!this.loading &&
scrollDirection === 'forward' &&
scrollOffset > (dataLen - 5) * itemSize + 100
) {
this.listReachBottom()
}
}}
/>
)
}
}
Props
column
类型: number
瀑布流占用列数量,默认值依照 width / columnWidth ||= 2 计算。
columnWidth
类型: number
瀑布流单列宽度,默认值依照 width / column 计算。
height
类型: number | string
列表的高度。
width
类型: number | string
列表的宽度。
item (必填)
类型: ReactComponent
推荐在 React 中使用 React.memo 或 React.PureComponent 进行优化,Vue 中也有相应优化方式。组件的 props 包括 id、index、data 和 isScrolling(当 useIsScrolling 为 true 时返回布尔值)。
itemCount (必填)
类型: number
列表的长度。
itemData (必填)
类型: Array<any>
渲染数据。
itemSize (必填)
类型: number | (index?: number, itemData?: Array<any>) => number
列表单项的大小。
unlimitedSize
类型: boolean
解开高度列表单项大小限制,默认使用 itemSize(注意初始高度与实际高度差异过大会导致隐患)。
position
类型: 'absolute' | 'relative' | 'brick'
布局方式,默认采用 "absolute"。其中 absolute 为绝对定位,relative 为相对定位并插入前置节点替代未显示单项的高度,brick 为相对定位但保留未显示单项节点(可能影响性能)。
initialScrollOffset (默认: 0)
类型: number
初始滚动偏移值。
overscanDistance (默认: 50)
类型: number
在可视区域之外预渲染的距离,值越高则白屏概率越小但滚动性能可能下降,建议至少大于等于 itemSize 的最大值。
placeholderCount (默认: 0)
类型: number
在可视区域之外占位的列表单项数量,值越高则白屏概率越小但性能可能下降。
upperThreshold (默认: 50)
类型: number
距离顶部多远时触发 onScrollToUpper 函数,单位为 px。
lowerThreshold (默认: 50)
类型: number
距离底部多远时触发 onScrollToLower 函数,单位为 px。
useIsScrolling
类型: boolean
是否向 item 组件注入 isScrolling 属性,适用于实现滚动骨架屏等场景。
enhanced (默认: true)
类型: boolean
通过 ScrollViewContext 优化组件滚动性能,部分平台可能不支持。
Events
scroll 事件
列表滚动时调用,参数对象包含 scrollDirection(滚动方向)、scrollOffset(滚动距离)和 scrollUpdateWasRequested(是否由 scrollTo 或 scrollToItem 触发)。
onScrollNative
类型: Function
调用平台原生的滚动监听函数。
onScrollToUpper
类型: Function
滚动到顶部时调用函数。
onScrollToLower
类型: Function
滚动到底部时调用函数。
Slots & Components
列表插槽
- renderTop: 顶部区域组件,类型为
ReactComponent<{ id: string }>。 - renderBottom: 底部区域组件,类型为
ReactComponent<{ id: string }>。
outerElementType
列表外部容器组件类型,默认值为 ScrollView,不建议替换为 View。
innerElementType
列表内部容器组件类型,默认值为 View。
itemElementType
列表子节点容器组件类型,默认值为 View。
Native Props
组件 ID
类型: string
根组件 ID,用于标识组件,不传入时会自动生成。
组件 CSS 类
根组件 CSS 类。
组件 CSS 样式
类型: Style
根组件的 CSS 样式。
其它 ScrollView 参数
除上述参数外,所有 ScrollView 组件的参数都可以传入 VirtualWaterfall 组件,冲突时优先使用文档描述的参数。
Methods
通过 React.createRef() 创建 ref 并挂载到 VirtualWaterfall 上,可以访问内部方法:
export default class Index extends Component {
state = {
data: buildData(0),
}
list = React.createRef()
componentDidMount() {
const list = this.list.current
list.scrollTo()
list.scrollToItem()
}
render() {
const { data } = this.state
const dataLen = data.length
return (
<VirtualWaterfall
height={500}
width="100%"
item={Row}
itemData={threads}
itemCount={threads.length}
itemSize={100}
/>
)
}
}
scrollTo
(scrollOffset: number, enhanced?: boolean): void
滚动到指定的地点,enhanced 默认为 props 传入的 enhanced 值。
scrollToItem
(index: number, align: string = "auto", enhanced?: boolean): void
滚动到指定的条目。align 参数可选值包括:
auto: 尽可能滚动距离最小保证条目在可视区域中。smart: 条目部分在可视区域时最小滚动,完全不在时居中显示。center: 让条目在可视区域居中显示。end: 让条目在可视区域末尾显示。start: 让条目在可视区域开始显示。
enhanced默认为 props 传入的 enhanced 值。