一、新建一个virtual-list.vue

<template>
  <!-- 虚拟列表 -->
  <view>
    <scroll-view :scroll-top="scrollTop" class="scroll-container" scroll-y="true" @scroll="scrollEvent"
      :style="{ height: containerHeight }">
      <!--可视区域里所有数据的渲染区域-->
      <view class="list" :style="{ top: top + 'px', ...customStyle }">
        <!--单条数据渲染区域-->
        <view v-for="(item, index) in showList" :key="index">
          <slot name="item" :row="item"></slot>
        </view>
      </view>
    </scroll-view>
  </view>
</template>

<script>
// 使用示例
// <virtual-list :sourceData="listAll" containerHeight="calc(100vh - 196rpx)" :itemHeight="200" :showNum="5" :customStyle="{ padding: '30rpx' }">
// 			<template v-slot:item="{ row }">
//       ......your code
// 			</template>
// </virtual-list>
// 刷新组件
// this.$refs.virtualList.refresh()
export default {
  props: {
    // 数据源
    sourceData: {
      type: Array,
      default: () => [],
      required: true
    },
    // 滚动容器总高度
    containerHeight: {
      type: String,
      default: '200px',
    },
    //每条数据所占高度
    itemHeight: {
      type: Number,
      default: 200,
      required: true
    },
    //每次加载到可视区域的数量,itemHeight X showNum 要大于可视区域高度 ,否则页面滚动不了
    showNum: {
      type: Number,
      default: 10,
      required: true
    },
    // 自定义列表样式
    customStyle: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      showList: [],  //可视区域显示的数据				
      top: 0, //偏移量
      scrollTop: 0,  //卷起的高度
      startIndex: 0,  //可视区域第一条数据的索引
      endIndex: 0,  //可视区域最后一条数据后面那条数据的的索引,因为后面要用slice(start,end)方法取需要的数据,但是slice规定end对应数据不包含在里面
    }
  },
  created() {
    //计算可视区域数据
    this.getShowList()
  },
  methods: {
    //计算可视区域数据
    getShowList() {
      this.startIndex = Math.floor(this.scrollTop / this.itemHeight)   //可视区域第一条数据的索引
      this.endIndex = this.startIndex + this.showNum   //可视区域最后一条数据的后面那条数据的索引
      this.showList = this.sourceData.slice(this.startIndex, this.endIndex)  //可视区域显示的数据,即最后要渲染的数据。实际的数据索引是从this.startIndex到this.endIndex-1
      this.top = this.scrollTop - (this.scrollTop % this.itemHeight)  //在这需要获得一个可以被itemHeight整除的数来作为item的偏移量,这样随机滑动时第一条数据都是完整显示的
    },
    //区域滚动事件
    scrollEvent(e) {
      this.scrollTop = e.detail.scrollTop
      this.getShowList()
    },
    // 刷新组件
    refresh() {
      setTimeout(() => {
        this.getShowList()
        this.scrollTop = 0
      })
    }
  }
}
</script>

<style scoped lang='scss'>
.scroll-container {
  position: relative;
  width: 100%;

  .list {
    position: absolute;
    width: 100%;
  }
}
</style>

 二、使用(下方代码是我使用的场景,你们可以自定义插槽中的内容)

<virtual-list ref="virtualList" :sourceData="taskList" containerHeight="calc(100vh - 196rpx)" :itemHeight="200"
			:showNum="5" :customStyle="{ padding: '30rpx' }">
			<template v-slot:item="{ row }">
				<view class="card">
					<view class="title">公章申请</view>
					<view class="row">
						<view class="fileds">创建日期:</view>
						<view class="content">2022-09-18 23:20:14</view>
					</view>
					<view class="row">
						<text class="fileds">申请人:</text>
						<text class="content">{{ row.name }}</text>
					</view>
					<view class="entry">
						<div class="name">查看详情</div>
						<div class="icon">&gt;</div>
					</view>
				</view>
			</template>
		</virtual-list>

 三、参数说明

属性

 sourceData:接收列表数据,传入数组即可

containerHeight:滚动容器的高度,接收例如 200px 的字符串

itemHeight:每条数据所占高度,传入数字,尽量在每一行的高度一致的列表使用,行高度差距非常大时不建议使用

showNum:滚动列表中能看到的行数量,保证 showNum *  itemHeight 大于 containerHeight  即可,可以自行调整数值,滚动顺滑即可

customStyle:自定义列表样式,接收style对象

方法

组件上定义ref="virtualList"

比例tab切换列表重新赋值后使用this.$refs.virtualList.refresh()刷新列表即可

作用域插槽

item

参数row, 数组遍历后单项的数据

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐