长列表渲染(虚拟列表) |
您所在的位置:网站首页 › 小程序虚拟列表滚动的时候闪烁 › 长列表渲染(虚拟列表) |
长列表渲染(虚拟列表) 在典型的 Taro 应用中,正常的列表渲染遵循以下的逻辑: 生成或从远程加载数据把数据加入框架的响应式数据中框架使用 diff 算法或其它机制根据数据的不同尝试全量更新视图Taro 运行时捕获框架的更新请求更新视图如果按照此逻辑,当第一步我们生成或加载的数据量非常大时就可能会产生严重的性能问题,导致视图无法响应操作一段时间。为了解决这个问题,我们可以采用另一种方式:比起全量渲染数据生成的视图,可以只渲染当前可视区域(visible viewport)的视图,非可视区域的视图在用户滚动到可视区域再渲染: 虚拟列表仅支持单列渲染,多列渲染请使用虚拟瀑布流组件。 示例基础示例ReactVue在 React Like 框架中我们可以直接从 @tarojs/components-advanced/dist/components/virtual-list 引入虚拟列表(VirtualList)组件: import VirtualList from '@tarojs/components-advanced/dist/components/virtual-list'一个最简单的长列表组件会像这样,VirtualList 的 6 个属性都是必填项: function buildData(offset = 0) { return Array(100) .fill(0) .map((_, i) => i + offset)}const Row = Reacmo(({ id, index, data }) => { return ( Row {index} : {data[index]} )})export default class Index extends Component { state = { data: buildData(0), } render() { const { data } = this.state const dataLen = data.length return ( ) }}在 Vue 中使用虚拟列表,我们需要在入口文件声明使用: // app.js 入口文件import Vue from 'vue'import registerVirtualList from '@tarojs/components-advanced/dist/components/virtual-list'// Note: 使用以下路径导出插件可以在 vue 中获得更好的类型支持// import registerVirtualList from '@tarojs/components-advanced/dist/components/virtual-list/vue'Vue.use(registerVirtualList)一个最简单的长列表组件会像这样,virtual-list 的 6 个属性都是必填项: Row {{ index }} : {{ data[index] }} export default { props: ['id', 'index', 'data'], } import { markRaw } from 'vue' import Row from './row.vue' function buildData(offset = 0) { return Array(100) .fill(0) .map((_, i) => i + offset) } export default { data() { return { Row: markRaw(Row), list: buildData(0), } }, }无限滚动实现无限滚动也非常简单,我们只需要在列表滚动到底部时,往列表尾部追加数据即可: ReactVueconst Row = Reacmo(({ id, index, data }) => { return ( Row {index} : {data[index]} )})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() // 如果 loading 与视图相关,那它就应该放在 `this.state` 里 // 我们这里使用的是一个同步的 API 调用 loading,所以不需要 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 ( { if ( // 避免重复加载数据 !this.loading && // 只有往前滚动我们才触发 scrollDirection === 'forward' && // 5 = (列表高度 / 单项列表高度) // 100 = 滚动提前加载量,可根据样式情况调整 scrollOffset > (dataLen - 5) * itemSize + 100 ) { this.listReachBottom() } }} /> ) }} import { markRaw } from 'vue' import Row from './row.vue' function buildData(offset = 0) { return Array(100) .fill(0) .map((_, i) => i + offset) } export default { data() { return { Row: markRaw(Row), list: buildData(0), loading: false, itemHeight: 100, } }, computed: { dataLen() { return this.list.length }, }, methods: { 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) }, onScroll({ scrollDirection, scrollOffset }) { if ( // 避免重复加载数据 !this.loading && // 只有往前滚动我们才触发 scrollDirection === 'forward' && // 5 = (列表高度 / 单项列表高度) // 100 = 滚动提前加载量,可根据样式情况调整 scrollOffset > (this.dataLen - 5) * this.itemHeight + 100 ) { this.listReachBottom() } }, }, }Propsheight类型: number | string 列表的高度。 3.6.10 及以下版本,当滚动方向为垂直时,height 必须为 number 类型。 width类型: number | string 列表的宽度。 3.6.10 及以下版本,当滚动方向为水平时,width 必须为 number 类型。 item (Required)ReactVue类型: ReactComponent (原 children 参数) 推荐使用 Reacmo 或 React.PureComponent 或使用 shouldComponentUpdate() 来优化此组件,避免不必要的渲染。 类型: VueComponent 推荐使用 markRaw 或使用 shallowReactive 来优化此组件。 将要渲染的列表单项组件。组件的 props 有 4 个属性: id: 单项的 ID,必须传入组件的 id 中index: 组件渲染数据的索引data: 组件渲染的数据,同虚拟瀑布流 itemDataisScrolling: 组件是否正在滚动,当 useIsScrolling 值为 true 时返回布尔值,否则返回 undefineditemCount (Required)类型: number 列表的长度。 itemData (Required)类型: Array 渲染数据。 itemSize (Required)类型: number | (index?: number, itemData?: Array) => number 列表单项的大小,垂直滚动时为高度,水平滚动时为宽度。 unlimitedSize类型: boolean 解开高度列表单项大小限制,默认值使用: itemSize (请注意,初始高度与实际高度差异过大会导致隐患)。 position类型: 'absolute' | 'relative' | 'brick' 布局方式,默认采用 "absolute" absolute:绝对定位布局模式,列表单项的位置由 top 和 left 决定relative:相对定位布局模式,插入前置节点替代未显示单项的高度brick:相对定位布局模式,未显示单项不移除,保留单项高度 (v3.6.10 及以下不支持)相比 relative 模式 brick 模式占用节点更多会导致一定性能问题,但保留未显示单项节点可提升部分场景显示速度layout类型: 'vertical' | 'horizontal'; 默认值: 'vertical' 滚动方向。vertical 为垂直滚动,horizontal 为平行滚动。默认为 vertical。 initialScrollOffset (Default: 0)类型: number 初始滚动偏移值。 水平滚动时,影响 scrollLeft 的值;垂直滚动时,影响 scrollTop 的值。overscanCount (Default: 1)类型: number 在可视区域之外渲染的列表单项数量,值设置得越高,快速滚动时出现白屏的概率就越小,相应地,每次滚动的性能会变得越差。 placeholderCount (Default: overscanCount)类型: number 在可视区域之外占位的列表单项数量,值设置得越高,快速滚动时出现白屏的概率就越小,相应地,每次滚动的性能会变得越差。 upperThreshold (Default: 50)类型: number, v3.6.10 及以下不支持 距离顶部多远时触发 onScrollToUpper 函数,单位为 px lowerThreshold (Default: 50)类型: number, v3.6.10 及以下不支持 距离底部多远时触发 onScrollToLower 函数,单位为 px useIsScrolling类型: boolean 是否注入 isScrolling 属性到 item 组件。这个参数一般用于实现滚动骨架屏(或其它 placeholder) 时比较有用。 enhanced (Default: false)类型: boolean 通过 ScrollViewContext 优化组件滚动性能 部分平台不支持,使用时请注意甄别 Eventsscroll 事件ReactVueonScroll: Function v-on:scroll: Function 列表滚动时调用函数,函数的第一个参数为对象,由三个属性构成: scrollDirection,滚动方向,可能值为 forward 往前, backward 往后。scrollOffset,滚动距离scrollUpdateWasRequested, 当滚动是由 scrollTo() 或 scrollToItem() 调用时返回 true,否则返回 falseonScrollNative类型: Function (原 scrollNative 参数) 调用平台原生的滚动监听函数。 Vue: onScrollToUpper类型: Function, v3.6.10 及以下不支持 滚动到顶部时调用函数 onScrollToLower类型: Function, v3.6.10 及以下不支持 滚动到底部时调用函数 Slots & Components列表插槽ReactVuerenderTop类型: ReactNode 顶部区域 renderBottom类型: ReactNode 底部区域 支持 top、bottom 两个插槽,分别对应顶部和底部区域 top bottom outerElementType列表外部容器组件类型。 ReactVue类型: ReactElement; 默认值: ScrollView 类型: string; 默认值: 'scroll-view' 处于考虑适配小程序原因,不建议使用 View 替换 ScrollView 组件作为 outerElementType。 innerElementType列表内部容器组件类型`。 ReactVue类型: ReactElement; 默认值: View 此容器的 parentNode 是 ScrollView,childNodes 是列表。 类型: string; 默认值: 'view' 此容器的 parentNode 是 scroll-view,childNodes 是列表。 itemElementType列表子节点容器组件类型。 ReactVue类型: ReactElement; 默认值: View 类型: string; 默认值: 'view' Native Props组件 IDid: string 根组件 ID,用于标识组件,不传入时会自动生成。 组件 CSS 类ReactVueclassName: string class: string (原 wclass 参数) 根组件 CSS 类。 组件 CSS 样式ReactVuestyle: Style style: Style (原 wstyle 参数) 根组件的 CSS 样式。 其它 ScrollView 参数除了以上参数,所有 ScrollView 组件的参数都可以传入 VirtualList 组件,冲突时优先使用以上文档描述的参数。 Methods通过 React.createRef() 创建 ref,挂载到 VirtualList 上可以访问到 VirtualList 的内部方法: 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 ( ) }}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 值。 相关问题在 Vue3 中使用虚拟列表需升级至 v3.6+ 版本 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |