# tui-virtual-list 虚拟列表 会员组件 V2.9.5+
介绍
虚拟列表,适用于显示同类的长列表数据类型,对渲染性能有一定的优化效果。
TIP
该组件需要与 tui-virtual-item 组件一起使用,需同时引入。
# 引入
# uni-app引入
第一种,手动引入(可全局引入)
import tuiVirtualList from "@/components/thorui/tui-virtual-list/tui-virtual-list.vue"
import tuiVirtualItem from "@/components/thorui/tui-virtual-item/tui-virtual-item.vue"
export default {
components:{
tuiVirtualList,
tuiVirtualItem
}
}
第二种,开启easycom组件模式,如果不了解如何配置,可先查看 官网文档 (opens new window)。
# uni-app版本平台差异说明
App-Nvue | App-vue | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|---|
升级中 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
# 微信小程序引入(可在app.json中全局引入)
{
"usingComponents": {
"tui-virtual-list": "/components/thorui/tui-virtual-list/tui-virtual-list",
"tui-virtual-item": "/components/thorui/tui-virtual-item/tui-virtual-item"
}
}
# 代码演示
部分功能演示,具体可参考示例程序以及文档API。
scroll-view 局部滚动使用示例
通过 itemBuffer
属性设置可视容器外加载的元素个数,background
属性设置容器背景色。
<template>
<view class="container">
<tui-virtual-list :itemBuffer="30" background="#fff" ref="virtualList" @change="onChange"
@scrolltolower="onScrollToLower">
<tui-virtual-item @click="itemClick(item)" v-for="(item,index) in virtualItems" :key="index">
<tui-list-cell padding="0">
<view class="tui-list__item">
<tui-lazyload-img width="68rpx" height="68rpx" radius="8rpx"
:src="item.avatar"></tui-lazyload-img>
<view class="tui-name">{{item.id +'-'+ item.name }}</view>
</view>
</tui-list-cell>
</tui-virtual-item>
</tui-virtual-list>
</view>
</template>
<script>
//数据列表可自行定义,示例文件请前往示例项目获取
import list from '@/utils/list.js'
let itemCount = 100
export default {
data() {
return {
startIndex: 0,
endIndex: 0,
disablePullUp: false,
//显示列表
virtualItems: [],
//数据源
items: list
}
},
onReady() {
this.updated(this.items)
},
methods: {
updated(items) {
const startTime = Date.now()
const virtualList = this.$refs.virtualList
virtualList && virtualList.render(items, () => {
const diffTime = Date.now() - startTime
console.log(`success - render time: ${diffTime}ms`)
})
},
loadData(e) {
if (this.items.length >= 1000 || this.disablePullUp) return
this.disablePullUp = true;
uni.showLoading({
title: '正在加载...'
})
setTimeout(() => {
const itemList = list.map(item => {
return {
id: item.id + itemCount,
name: item.name,
avatar: item.avatar,
}
})
this.items = this.items.concat(itemList)
itemCount += 100
this.updated(this.items)
this.disablePullUp = false;
uni.hideLoading()
}, 1000)
console.log('loadData', e)
},
onChange(e) {
const {
startIndex,
endIndex,
items
} = e
console.log('onChange', e)
if (this.startIndex !== startIndex || this.endIndex !== endIndex) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.virtualItems = items
}
},
onScrollToLower(e) {
this.loadData(e)
console.log('onScrollToLower', e)
},
itemClick(e) {
console.log(e)
}
}
}
</script>
<style>
.tui-list__item {
width: 100%;
height: 100rpx;
padding: 16rpx 30rpx;
box-sizing: border-box;
display: flex;
align-items: center;
}
.tui-name {
width: 90%;
font-size: 32rpx;
padding-left: 20rpx;
padding-right: 40rpx;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
<tui-virtual-list itemBuffer="{{30}}" background="#fff" id="virtualList" bindchange="onChange" bindscrolltolower="onScrollToLower">
<tui-virtual-item bindclick="itemClick" data-item="{{item}}" wx:for="{{virtualItems}}" wx:key="index">
<tui-list-cell padding="0">
<view class="tui-list__item">
<tui-lazyload-img width="68rpx" height="68rpx" radius="8rpx" src="{{item.avatar}}"></tui-lazyload-img>
<view class="tui-name">{{item.id +'-'+ item.name }}</view>
</view>
</tui-list-cell>
</tui-virtual-item>
</tui-virtual-list>
//数据列表可自行定义,示例文件请前往示例项目获取
import list from '../../../utils/list.js'
let virtualList;
Page({
data: {
itemCount:100,
startIndex: 0,
endIndex: 0,
disablePullUp: false,
//显示列表
virtualItems: [],
//数据源
items: list
},
onLoad(options) {
},
onReady() {
virtualList = this.selectComponent('#virtualList')
this.updated(this.data.items)
},
updated(items) {
const startTime = Date.now()
virtualList && virtualList.render(items, () => {
const diffTime = Date.now() - startTime
console.log(`success - render time: ${diffTime}ms`)
})
},
loadData(e) {
if (this.data.items.length >= 1000 || this.data.disablePullUp) return
this.data.disablePullUp = true;
wx.showLoading({
title: '正在加载...'
})
setTimeout(() => {
const itemList = list.map(item => {
return {
id: item.id + this.data.itemCount,
name: item.name,
avatar: item.avatar,
}
})
this.data.items = this.data.items.concat(itemList)
this.data.itemCount += 100
this.updated(this.data.items)
this.data.disablePullUp = false;
wx.hideLoading()
}, 1000)
console.log('loadData', e.detail)
},
onChange(e) {
const {
startIndex,
endIndex,
items
} = e.detail
console.log('onChange', e.detail)
if (this.data.startIndex !== startIndex || this.data.endIndex !== endIndex) {
this.data.startIndex = startIndex;
this.data.endIndex = endIndex;
this.setData({
virtualItems: items
})
}
},
onScrollToLower(e) {
this.loadData(e)
console.log('onScrollToLower', e.detail)
},
itemClick(e) {
const item = e.currentTarget.dataset.item
console.log(item)
}
})
.tui-list__item {
width: 100%;
height: 100rpx;
padding: 16rpx 30rpx;
box-sizing: border-box;
display: flex;
align-items: center;
}
.tui-name {
width: 90%;
font-size: 32rpx;
padding-left: 20rpx;
padding-right: 40rpx;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// Make sure to add code blocks to your code group
PageScroll 页面滚动使用示例
通过 enablePageScroll
属性设置是否启用页面滚动,item-height
属性设置子项高度, itemBuffer
属性设置可视容器外加载的元素个数,background
属性设置容器背景色。
<template>
<view class="container">
<tui-virtual-list enablePageScroll :item-height="120" :itemBuffer="50" background="#fff" ref="virtualList"
@change="onChange">
<tui-virtual-item @click="itemClick(item)" v-for="(item,index) in virtualItems" :key="index">
<tui-list-cell padding="0">
<view class="tui-list__item" :style="{height:itemHeight+'px'}">
<tui-lazyload-img width="72rpx" height="72rpx" radius="8rpx"
:src="item.avatar"></tui-lazyload-img>
<view class="tui-name">{{item.id +'-'+ item.name }}</view>
</view>
</tui-list-cell>
</tui-virtual-item>
</tui-virtual-list>
<tui-loadmore v-if="disablePullUp"></tui-loadmore>
</view>
</template>
<script>
import list from '@/utils/list.js'
let itemCount = 100
export default {
data() {
return {
startIndex: 0,
endIndex: 0,
disablePullUp: false,
//显示列表
virtualItems: [],
//数据源
items: list,
//组件传入为rpx值,组件内会转化为px,初始化事件返回px值
itemHeight: 60
}
},
onReady() {
this.updated(this.items)
},
methods: {
updated(items) {
const startTime = Date.now()
const virtualList = this.$refs.virtualList
virtualList && virtualList.render(items, () => {
const diffTime = Date.now() - startTime
console.log(`success - render time: ${diffTime}ms`)
})
},
loadData() {
if (this.items.length >= 5000 || this.disablePullUp) return
this.disablePullUp = true;
uni.showLoading({
title: '正在加载...'
})
setTimeout(() => {
const itemList = list.map(item => {
return {
id: item.id + itemCount,
name: item.name,
avatar: item.avatar,
}
})
this.items = this.items.concat(itemList)
itemCount += 100
this.updated(this.items)
this.disablePullUp = false;
uni.hideLoading()
uni.stopPullDownRefresh()
}, 1000)
console.log('loadData')
},
init(e) {
this.itemHeight = e.itemHeight
},
onChange(e) {
const {
startIndex,
endIndex,
items
} = e
console.log('onChange', e)
if (this.startIndex !== startIndex || this.endIndex !== endIndex) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.virtualItems = items
}
},
itemClick(item) {
console.log(item)
}
},
onPageScroll(e) {
// 当页面滚动时调用组件 onScroll 方法
const virtualList = this.$refs.virtualList
virtualList && virtualList.onScroll({
detail: e
})
},
onReachBottom() {
this.loadData()
console.log('onReachBottom')
},
onPullDownRefresh() {
itemCount = 0
this.items = []
this.loadData()
console.log('onPullDownRefresh')
}
}
</script>
<style>
.tui-list__item {
width: 100%;
height: 120rpx;
padding: 16rpx 30rpx;
box-sizing: border-box;
display: flex;
align-items: center;
}
.tui-name {
width: 90%;
font-size: 32rpx;
padding-left: 20rpx;
padding-right: 40rpx;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
<view class="container">
<tui-virtual-list enablePageScroll item-height="{{120}}" itemBuffer="{{50}}" background="#fff" id="virtualList" bindinit="init" bindchange="onChange">
<tui-virtual-item bindclick="itemClick" data-item="{{item}}" wx:for="{{virtualItems}}" wx:key="index">
<tui-list-cell padding="0">
<view class="tui-list__item" style="height: {{itemHeight}}px;">
<tui-lazyload-img width="72rpx" height="72rpx" radius="8rpx" src="{{item.avatar}}"></tui-lazyload-img>
<view class="tui-name">{{item.id +'-'+ item.name }}</view>
</view>
</tui-list-cell>
</tui-virtual-item>
</tui-virtual-list>
<tui-loadmore wx:if="{{disablePullUp}}"></tui-loadmore>
</view>
//数据列表可自行定义,示例文件请前往示例项目获取
import list from '../../../utils/list.js'
let virtualList;
Page({
data: {
startIndex: 0,
endIndex: 0,
disablePullUp: false,
//显示列表
virtualItems: [],
//数据源
items: [...list],
itemCount: 100,
//传入为rpx值,组件内会转化为px,初始化事件返回值
itemHeight: 60
},
onLoad(options) {
},
onReady() {
virtualList = this.selectComponent('#virtualList')
this.updated(this.data.items)
},
updated(items) {
const startTime = Date.now()
virtualList && virtualList.render(items, () => {
const diffTime = Date.now() - startTime
console.log(`success - render time: ${diffTime}ms`)
})
},
init(e) {
this.setData({
itemHeight: e.detail.itemHeight
})
},
loadData() {
if (this.data.items.length >= 5000 || this.data.disablePullUp) return
this.data.disablePullUp = true;
wx.showLoading({
title: '正在加载...'
})
setTimeout(() => {
const itemList = list.map(item => {
return {
id: item.id + this.data.itemCount,
name: item.name,
avatar: item.avatar,
}
})
this.data.items = this.data.items.concat(itemList)
this.data.itemCount += 100
this.updated(this.data.items)
this.data.disablePullUp = false;
wx.hideLoading()
wx.stopPullDownRefresh()
}, 1000)
console.log('loadData')
},
onChange(e) {
const {
startIndex,
endIndex,
items
} = e.detail
console.log('onChange', e.detail)
if (this.data.startIndex !== startIndex || this.data.endIndex !== endIndex) {
this.data.startIndex = startIndex;
this.data.endIndex = endIndex;
this.setData({
virtualItems: items
})
}
},
itemClick(e) {
const item = e.currentTarget.dataset.item
console.log(item)
},
onPageScroll(e) {
// 当页面滚动时调用组件 onScroll 方法
virtualList && virtualList.onScroll({
detail: e
})
},
onReachBottom() {
this.loadData()
console.log('onReachBottom')
},
onPullDownRefresh() {
this.data.itemCount = 0
this.data.items = []
this.loadData()
console.log('onPullDownRefresh')
}
})
.tui-list__item {
width: 100%;
height: 120rpx;
padding: 16rpx 30rpx;
box-sizing: border-box;
display: flex;
align-items: center;
}
.tui-name {
width: 90%;
font-size: 32rpx;
padding-left: 20rpx;
padding-right: 40rpx;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// Make sure to add code blocks to your code group
# Slots
tui-virtual-list 组件
插槽名称 | 说明 |
---|---|
default | 列表内容,由多个tui-virtual-item组成 |
tui-virtual-item 组件
插槽名称 | 说明 |
---|---|
default | 自定义显示item项内容 |
# Props
tui-virtual-list 组件
属性名 | 类型 | 说明 | 默认值 |
---|---|---|---|
height | Number, String | 容器高度 | 600 |
unit | String | 容器高度单位,可选值rpx、px | rpx |
background | String | 容器背景色 | transparent |
enablePageScroll | Boolean | 是否启用页面滚动,默认使用 scroll-view 滚动 | false |
itemHeight | Number, String | 子元素高度,单位rpx | 100 |
itemBuffer | Number, String | 可视容器外加载的元素个数,值越大性能越高 | 0 |
currentIndex | Number, String | 设置滚动条到对应子元素的位置 | 0 |
upperThreshold | Number, String | 距顶部多远时,触发 scrolltoupper 事件,单位px | 50 |
lowerThreshold | Number, String | 距底部多远时,触发 scrolltolower 事件,单位px | 50 |
scrollWithAnimation | Boolean | 在设置滚动条位置时使用动画过渡 | false |
enableBackToTop | Boolean | iOS 点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向 | false |
tui-virtual-item 组件
属性名 | 类型 | 说明 | 默认值 |
---|---|---|---|
- | - | - | - |
# Events
tui-virtual-list 组件
事件名 | 说明 | 回调参数 |
---|---|---|
init | 初始化回调函数 | { itemHeight: item项高度 px } |
change | 数据变化时的回调函数 | { e: 对象数据 } |
scroll | 滚动时触发,使用scroll-view滚动时使用 | { e: 对象数据 } |
scrolltoupper | 滚动到顶部时触发,使用scroll-view滚动时使用 | { e: 对象数据 } |
scrolltolower | 滚动到底部时触发,使用scroll-view滚动时使用 | { e: 对象数据 } |
tui-virtual-item 组件
事件名 | 说明 | 回调参数 |
---|---|---|
click | 点击时触发 | { } |
# Methods
如何调用方法详见 进阶用法 介绍
tui-virtual-list 组件
方法名 | 说明 | 传入参数 |
---|---|---|
render | 用于动态加载数据 | items, callback |
scrollTo | 滚动到指定的位置 | scrollOffset, callback |
scrollToIndex | 根据索引值滚动到指定的位置 | index, callback |
onScroll | 启用页面滚动时需要手动设置 | e |
//方法及参数详细说明
/**
* 更新组件
* @param {Array} items 实际数据列表,当需要动态加载数据时设置
* @param {Function} callback 设置完成后的回调函数
*/
render(items, callback)
/**
* 滚动到指定的位置
* @param {Number} scrollOffset 指定的位置
* @param {Function} callback 设置完成后的回调函数
*/
scrollTo(scrollOffset, callback)
/**
* 根据索引值滚动到指定的位置
* @param {Number} index 指定元素的索引值
* @param {Function} callback 设置完成后的回调函数
*/
scrollToIndex(index, callback)
/**
* 滚动时触发的事件,启用页面滚动时需要在 onPageScroll 中 手动设置
* @param {Object} e 表示事件对象
*/
onScroll(e)
# 预览
请以移动端效果为准,touch事件目前尚未在PC端做兼容。
# 特别说明
该组件为 会员组件
,非开源内容,需开通会员才可获取使用。
# 线上程序扫码预览
![]() | ![]() | ![]() |
---|---|---|
ThorUI组件库小程序码 | H5二维码 | ThorUI示例小程序码 |