# tui-virtual-table 虚拟化表格 会员组件 V3.0.0+

介绍

虚拟列表,适用于显示同类的长列表数据类型,对渲染性能有一定的优化效果。

TIP

该组件内部使用了 tui-icon 组件,需同时引入使用,uniapp非easycom模式下需要在组件内手动进行引入。

# 引入

# uni-app引入

第一种,手动引入(可全局引入)

import tuiVirtualTable from "@/components/thorui/tui-virtual-table/tui-virtual-table.vue"
export default {
	components:{
		tuiVirtualTable
	}
}

第二种,开启easycom组件模式,如果不了解如何配置,可先查看 官网文档 (opens new window)

# uni-app版本平台差异说明

App-Nvue App-vue H5 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
升级中

# 微信小程序引入(可在app.json中全局引入)

{
  "usingComponents": {
    "tui-virtual-table": "/components/thorui/tui-virtual-table/tui-virtual-table"
  }
}

# 代码演示

部分功能演示,具体可参考示例程序以及文档API。

使用示例

注意:数据文件请根据路径从示例中获取。

    <template>
    	<view class="container">
    		<view class="tui-page__hd">
    			<view class="tui-page__title">VirtualTable</view>
    			<view class="tui-page__desc">虚拟化表格,对长列表数据渲染性能有一定的优化效果。</view>
    		</view>
    		<view class="tui-page__bd">
    			<view class="tui-title" style="padding-top: 0;">基础使用/高度自适应</view>
    			<view class="tui-table--box">
    				<tui-virtual-table full :height="0" item-height="0" :table-data="tableData"
    					:header="headers"></tui-virtual-table>
    			</view>
    
    			<view class="tui-title">通栏/斑马纹/item高度100rpx</view>
    			<tui-virtual-table full stripe :item-height="100" :height="0" :table-data="tableData"
    				:header="headers"></tui-virtual-table>
    
    			<view class="tui-title">容器高度600rpx,item高度:120rpx,长列表加载</view>
    			<tui-virtual-table :itemBuffer="50" :item-height="120" ref="virtualList" fixed :header="header"
    				@click="detail" @scrolltolower="onScrollToLower"></tui-virtual-table>
    
    			<view class="tui-title">总高度720rpx,item高度:120rpx,排序(一次性加载时使用)</view>
    			<tui-virtual-table full outside-header :height="600" :itemBuffer="50" :item-height="120" ref="virtualList2" fixed
    				:header="header2" @click="detail" @sortChange="sortChange"></tui-virtual-table>
    
    			<view class="tui-title">选择框</view>
    			<tui-virtual-table :height="0" selection full :table-data="tableData" :header="headers"
    				@selectionChange="change" ref="table"></tui-virtual-table>
    		</view>
    	</view>
    </template>
    
    <script>
    	import list from '@/utils/list.js'
    	let itemCount = 100
    	const tableData = [{
    			"id": 1,
    			"name": "阿拉斯加",
    			"mobile": "13588889999",
    			"avatar": "https://thorui.cn/extend/avatar/1.jpg"
    		},
    		{
    			"id": 2,
    			"name": "阿克苏",
    			"mobile": "0551-4386721",
    			"avatar": "https://thorui.cn/extend/avatar/2.jpg"
    		}, {
    			"id": 3,
    			"name": "阿拉善",
    			"mobile": "4008009100",
    			"avatar": "https://thorui.cn/extend/avatar/3.jpg"
    		}, {
    			"id": 4,
    			"name": "阿勒泰",
    			"mobile": "13588889999",
    			"avatar": "https://thorui.cn/extend/avatar/4.jpg"
    		}
    	]
    	export default {
    		data() {
    			return {
    				disablePullUp: false,
    				tableData: tableData,
    				headers: [{
    					prop: 'id',
    					label: '编号'
    				}, {
    					prop: 'name',
    					label: '名称'
    				}, {
    					prop: 'mobile',
    					label: '电话'
    				}],
    				itemsList: list,
    				//数据源
    				items: list,
    				header: [{
    					prop: 'id',
    					label: '编号',
    					fixed: true,
    				}, {
    					prop: 'name',
    					label: '名称'
    				}, {
    					prop: 'mobile',
    					label: '电话',
    					width: 280,
    				}, {
    					prop: 'avatar',
    					label: '头像',
    					width: 200,
    					imgWidth: 80,
    					type: 2
    				}, {
    					label: '操作',
    					fixed: 'right',
    					type: 3,
    					width: 160,
    					buttons: [{
    						text: '查看',
    						color: '#5677fc',
    						fontWeight: 600
    					}]
    				}],
    				header2: [{
    					prop: 'id',
    					label: '编号',
    					//是否开启排序
    					sortable: true,
    					//排序图标颜色
    					sortColor: '#5677fc',
    					//必传:排序数据类型
    					sortType: 'number'
    				}, {
    					prop: 'name',
    					label: '名称',
    					sortable: true,
    					sortColor: '#5677fc',
    					sortType: 'string'
    				}, {
    					prop: 'avatar',
    					label: '头像',
    					type: 2
    				},{
    					label: '操作',
    					type: 3,
    					buttons: [{
    						text: '查看',
    						color: '#5677fc',
    						fontWeight: 600
    					}]
    				}]
    			}
    		},
    		onReady() {
    			this.initData(this.items)
    			//排序列表,一次行数据渲染
    			const virtualList2 = this.$refs.virtualList2
    			virtualList2 && virtualList2.render(this.items, () => {})
    		},
    		methods: {
    			initData(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,
    							mobile: item.mobile
    						}
    					})
    					this.items = this.items.concat(itemList)
    					itemCount += 100
    					this.initData(this.items)
    					this.disablePullUp = false;
    					uni.hideLoading()
    				}, 500)
    				console.log('loadData', e)
    			},
    			onScrollToLower(e) {
    				console.log('onScrollToLower', e)
    				if (e.direction == 'bottom') {
    					this.loadData(e)
    				}
    			},
    			itemClick(e) {
    				console.log(e)
    			},
    			sortChange(e) {
    				//排序数据发生改变时触发
    				console.log(e)
    			},
    			detail(e) {
    				console.log(JSON.stringify(e))
    				uni.previewImage({
    					urls: [e.item.avatar]
    				})
    			},
    			change(e) {
    				console.log(e)
    				const names = e.map(item => item.name)
    				this.tui.toast(names.join(',') || '取消选择')
    			}
    		}
    	}
    </script>
    
    <style>
    	.tui-title {
    		width: 100%;
    		font-size: 24rpx;
    		color: #999;
    		padding: 64rpx 30rpx 30rpx;
    		box-sizing: border-box;
    	}
    
    	.tui-table--box {
    		width: 100%;
    		padding: 0 30rpx;
    		box-sizing: border-box;
    	}
    </style>
    	
    
    <view class="container">
      <view class="tui-page__hd">
        <view class="tui-page__title">VirtualTable</view>
        <view class="tui-page__desc">虚拟化表格,对长列表数据渲染性能有一定的优化效果。</view>
      </view>
      <view class="tui-page__bd">
        <view class="tui-title" style="padding-top: 0;">基础使用/高度自适应</view>
        <view class="tui-table--box">
          <tui-virtual-table full height="0" item-height="0" table-data="{{tableData}}" header="{{headers}}"></tui-virtual-table>
        </view>
    
        <view class="tui-title">通栏/斑马纹/item高度100rpx</view>
        <tui-virtual-table full stripe item-height="{{100}}" height="{{0}}" table-data="{{tableData}}" header="{{headers}}"></tui-virtual-table>
    
        <view class="tui-title">容器高度600rpx,item高度:120rpx,长列表加载</view>
        <tui-virtual-table itemBuffer="{{30}}" item-height="{{120}}" id="virtualList" fixed header="{{header}}" bindclick="detail" bindscrolltolower="onScrollToLower"></tui-virtual-table>
    
        <view class="tui-title">容器高度720rpx,item高度:120rpx,排序(一次性加载时使用)</view>
        <tui-virtual-table full outsideHeader height="{{600}}" itemBuffer="{{30}}" item-height="{{120}}" id="virtualList2" fixed header="{{header2}}" bindclick="detail" bind:sortChange="sortChange"></tui-virtual-table>
    
        <view class="tui-title">选择框</view>
        <tui-virtual-table height="{{0}}" selection full table-data="{{tableData}}" header="{{headers}}" bindselectionChange="change" id="table"></tui-virtual-table>
      </view>
    </view>
    
    import list from '../../../utils/list.js'
    let itemCount = 100;
    const tableData = [{
        "id": 1,
        "name": "阿拉斯加",
        "mobile": "13588889999",
        "avatar": "https://thorui.cn/extend/avatar/1.jpg"
      },
      {
        "id": 2,
        "name": "阿克苏",
        "mobile": "0551-4386721",
        "avatar": "https://thorui.cn/extend/avatar/2.jpg"
      }, {
        "id": 3,
        "name": "阿拉善",
        "mobile": "4008009100",
        "avatar": "https://thorui.cn/extend/avatar/3.jpg"
      }, {
        "id": 4,
        "name": "阿勒泰",
        "mobile": "13588889999",
        "avatar": "https://thorui.cn/extend/avatar/4.jpg"
      }
    ]
    let virtualList2, virtualList;
    Page({
      data: {
        disablePullUp: false,
        tableData: tableData,
        headers: [{
          prop: 'id',
          label: '编号'
        }, {
          prop: 'name',
          label: '名称'
        }, {
          prop: 'mobile',
          label: '电话'
        }],
        itemsList: list,
        //数据源
        items: list,
        header: [{
          prop: 'id',
          label: '编号',
          fixed: true
        }, {
          prop: 'name',
          label: '名称'
        }, {
          prop: 'mobile',
          label: '电话',
          width: 280,
        }, {
          prop: 'avatar',
          label: '头像',
          width: 200,
          imgWidth: 80,
          type: 2
        }, {
          label: '操作',
          fixed: 'right',
          type: 3,
          width: 160,
          buttons: [{
            text: '查看',
            color: '#5677fc',
            fontWeight: 600
          }]
        }],
        header2: [{
          prop: 'id',
          label: '编号',
          //是否开启排序
          sortable: true,
          //排序图标颜色
          sortColor: '#5677fc',
          //必传:排序数据类型
          sortType: 'number'
        }, {
          prop: 'name',
          label: '名称',
          sortable: true,
          sortColor: '#5677fc',
          sortType: 'string'
        }, {
          prop: 'avatar',
          label: '头像',
          type: 2
        },{
          label: '操作',
          type: 3,
          buttons: [{
            text: '查看',
            color: '#5677fc',
            fontWeight: 600
          }]
        }]
      },
      onLoad(options) {
    
      },
      onReady() {
        virtualList = this.selectComponent('#virtualList')
        virtualList2 = this.selectComponent('#virtualList2')
        this.initData(this.data.items)
        //排序列表
        virtualList2 && virtualList2.render(this.data.items, () => {})
      },
      initData(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 + itemCount,
              name: item.name,
              avatar: item.avatar,
              mobile: item.mobile
            }
          })
          this.data.items = this.data.items.concat(itemList)
          itemCount += 100
          this.initData(this.data.items)
          this.data.disablePullUp = false;
          wx.hideLoading()
        }, 500)
        console.log('loadData', e)
      },
      onScrollToLower(e) {
        console.log('onScrollToLower', e.detail)
        if (e.detail.direction == 'bottom') {
          this.loadData(e.detail)
        }
      },
      itemClick(e) {
        console.log(e.detail)
      },
      sortChange(e) {
        //排序数据发生改变时触发
        console.log(e.detail)
      },
      detail(e) {
        const detail = e.detail
        console.log(JSON.stringify(detail))
        wx.previewImage({
          urls: [detail.item.avatar]
        })
      },
      change(e) {
        const data = e.detail;
        console.log(data)
        const names = data.map(item => item.name)
        wx.tui.toast(names.join(',') || '取消选择')
      }
    })
    
    .tui-title {
      width: 100%;
      font-size: 24rpx;
      color: #999;
      padding: 64rpx 30rpx 30rpx;
      box-sizing: border-box;
    }
    
    .tui-table--box {
      width: 100%;
      padding: 0 30rpx;
      box-sizing: border-box;
    }
    
    // Make sure to add code blocks to your code group

    # Slots

    插槽名称 说明
    - -

    # Props

    属性名 类型 说明 默认值
    height Number, String 表格容器高度,传0则为普通表格,不进行长列表优化 600
    unit String 表格容器高度单位,可选值:rpx、px rpx
    background String 背景色 #fff
    itemHeight Number, String 表格行(tr)高度 ,单位rpx 100
    itemBuffer Number, String 可视容器外加载的元素个数,值越大性能越高 0
    upperThreshold Number, String 距顶部多远时,触发 scrolltoupper 事件,单位px 50
    lowerThreshold Number, String 距底部多远时,触发 scrolltolower 事件,单位px 50
    enableBackToTop Boolean iOS 点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向 false
    header Array 表头数据,必选参数 [ ]
    outsideHeader Boolean 表头是否放置容器外,仅建议横向数据不超过一屏时使用 false
    size Number, String 表头字体大小,单位rpx 28
    color String 表头字体颜色 #333
    fontWeight Number, String 表头字重 600
    headerBgColor String 表头背景色 #fff
    fixed Boolean 表头是否固定在顶部,outsideHeader为true时默认固定 false
    tableData Array 表格数据 [ ]
    full Boolean 表格宽度是否铺满剩余空间,仅数据列不超过一屏时使用 false
    border Boolean 是否带有纵向边框 true
    horBorder Boolean 是否带有横向边框 true
    borderColor String 边框颜色 #eee
    stripe Boolean 是否为斑马纹(隔行换色) false
    stripeColor String 斑马纹颜色 #F8F8F8
    textSize Number, String 表格内容字体大小,单位rpx 28
    textColor String 表格内容字体颜色 #333
    align String 单元格对齐方式,可选值:left、center、right center
    ellipsis Boolean 文字超出是否省略,默认换行 false
    padding Number, String 单元格上下padding值,单位rpx 20
    selection Boolean 是否添加多选框 false
    initEmitChange Boolean 首次加载是否触发 selectionChange 事件 false
    checkboxColor String 选择框选中后颜色 #5677fc
    checkboxBorderColor String 选择框未选中时边框颜色 #eee
    checkmarkColor String 选择框选中时对号颜色 #fff
    emptyText String 表格数据为空时提示文本 暂无数据
    emptySize String, Number 表格数据为空时提示文本字体大小,单位rpx 24
    emptyColor String 表格数据为空时提示文本字体颜色 #bfbfbf
    londingType String, Number 占位类型, 1-显示加载文本 2-显示骨架 2
    loadingText String 加载文本内容 加载中...
    loadingColor String 加载文本字体颜色 #999
    isVirtual Boolean 是否为虚拟table,设为false时,滚动抖动或出现骨架情况有一定优化 true
    //header 表头属性详细说明
    [{
    	//表格内容类型:1-text 展示文本 2-image 展示图片 3-button 展示操作按钮,必选
    	type: 1,
    	//表头显示名称,可选,内容为空时显示prop
    	label: '姓名',
    	//当前列展示数据属性名,结合实际数据传入,必选
    	prop: 'name',
    	//单元格宽度,单位rpx
    	width: 200,
    	//当前列是否吸顶固定:true-左侧固定,left-左侧固定,right-右侧固定,可选
    	fixed: true,
    	//表头字体大小,单位rpx,优先级大于props中size值,可选
    	size:28,
    	//表头文字颜色,优先级大于props中color值,可选
    	color: '',
    	//单元格字体大小,单位rpx,优先级大于props中textSize值,可选
    	textSize:28,
    	//单元格文字颜色,优先级大于props中textColor值,可选
    	textColor: '',
    	//图片宽度,单位rpx ,type=2时有效
    	imgWidth: 80,
    	//图片高度度,单位rpx ,type=2时有效
    	imgHeight: 80,
    	//列单元格对齐方式:left/center/right,优先级大于props中align值,可选 
    	align:'',
    	//按钮数据,,type=3时有效,可选
    	buttons: [{
    		//按钮文本
    		text: '查看',
    		//按钮文本颜色
    		color: '#5677fc',
    		//按钮字体大小
    		size: 28,
    		//按钮字重
    		fontWeight: 400
    	}],
    	//[可选] 是否开启排序
    	sortable: true,
    	//[开启排序后则必填] 排序数据类型,可选值:number/date/string 
    	sortType: 'date',
    	//[可选] 排序图标颜色,不传值则使用默认值 
    	sortColor: '#465CFF',
    	//[可选] 排序图标right值,默认40(单位rpx),根据列宽度自行调整至合适的位置 
    	sortRight:40,
    	//[可选] 排序图标大小,单位rpx 
    	sortSize:28
    }]
    

    # Events

    事件名 说明 回调参数
    change 数据变化时的回调函数 { e: 对象数据 }
    scroll 滚动时触发,使用scroll-view滚动时使用 { e: 对象数据 }
    scrolltoupper 滚动到顶部时触发,使用scroll-view滚动时使用 { e: 对象数据 }
    scrolltolower 滚动到底部时触发,使用scroll-view滚动时使用 { e: 对象数据 }
    click 点击按钮时触发,表头数据type=3时有效 {
      index:数据行索引,
      item:对应数据行数据
      btnIndex:按钮索引
    }
    trClick 点击行时触发 {
      index:数据行索引,
      item:对应数据行数据
    selectionChange 当选择项发生变化时会触发该事件 selection:选中数据
    select 勾选行 Checkbox 时触发的事件 {
      index:数据行索引,
      item:对应数据行数据,
      is_selected:是否选中
    }
    selectAll 勾选全选 Checkbox 时触发的事件 {
      is_selected:是否全选
    }
    sortChange 排序数据发生改变时触发 {
      itemList:排序后列表,
      virtualItems:虚拟列表,展示的内容数据,
      sort:排序方式
      prop:排序属性字段
    }

    # Methods

    如何调用方法详见 进阶用法 介绍

    方法名 说明 传入参数
    render 用于动态加载数据,长列表使用时必须调用此方法展示数据 items, callback
    scrollTo 滚动到指定的位置 scrollOffset, callback
    scrollToIndex 根据索引值滚动到指定的位置 index, callback
    clearSelection 用于多选表格,清空用户的选择 -
    toggleRowSelection 用于多选表格,切换某一行的选中状态   row:行数据
      selected:是否选中
    toggleRowDisabled 用于多选表格,切换某一行的禁用状态   row:行数据
      disabled:是否禁用
    toggleAllSelection 用于多选表格,切换所有行的选中状态 -
    resetSort 用于有设置排序表格,重置所有排序 -
    setSort 用于有设置排序表格,设置排序   prop:需要排序的字段
      sortOrder:排序方式
      (ascending/descending)
    //部分方法及参数详细说明
    
    /**
     * 更新组件
     * @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) 
    
    
    /**
     * 用于多选表格,清空用户的选择
     */
    clearSelection()
    
    // ...
    

    # 预览

    请以移动端效果为准,touch事件目前尚未在PC端做兼容。

    # 特别说明

    该组件为 会员组件,非开源内容,需开通会员才可获取使用。

    # 线上程序扫码预览

    ThorUI组件库 H5二维码 ThorUI示例
    ThorUI组件库小程序码 H5二维码 ThorUI示例小程序码
    Last Updated: 5/22/2024, 5:51:54 PM