vue虚拟列表展示

效果图

在这里插入图片描述
在这里插入图片描述


<template>
  <!-- 总体高度区域 -->
  <div
    ref="listWrap"
    class="m-container"
    @scroll="scrollListener"
  >
    <div
      :style="handleContainerHeight()"
    >
      <!-- 可视区域 -->
      <div
        class="m-area"
        :style="handleAreaStyle()"
      >
        <div
          v-for="(item,index) in displayList"
          :key="index"
          :style="handleItemStyle()"
        >
          {{ item.name }}
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
interface ListType {
  label: string;
  value: string;
}
@Options({
  props: {
    list: {
      default:[],
    },
  },
})
export default class MList extends Vue {
  list!: ListType[];
  /** 每行高度 */
  itemSize = 100;
  /** 一次性展示多少个数据 */
  showNum = 10;
  /** 开始下标 */
  start =0;
  /** 结束下标 */
  end = 10;
  /** 滚动位置 */
  scrollTop = 0;

  get displayList() {
    const arr = this.list.slice(this.start,this.end);
    if(arr.length) {
      return arr;
    }

    return [];
  }

  handleItemStyle() {
    return {
      height: `${this.itemSize}px`,
    };
  }

  handleContainerHeight() {
    return {
      height: this.list.length * this.itemSize + 'px',
    };
  }

  handleAreaStyle() {
    return {
      'transform': `translateY(${this.scrollTop}px)`,
    };
  }

  scrollListener() {
    this.scrollTop = (this.$refs.listWrap.scrollTop as number);
    this.start = Math.floor(this.scrollTop/this.itemSize);
    this.end = this.start + this.showNum;
  }

}
</script>
<style scoped>
.m-container {
  height: 100vh;
  overflow: auto;
}
</style>


### 如何在 Vue.js 中实现虚拟列表 #### 背景 在现代前端开发中,当需要展示大量数据时,直接渲染所有项目可能会导致性能瓶颈。为了优化这种情况,可以采用 **虚拟列表** 技术来提升应用的性能[^2]。 --- #### 原理概述 虚拟列表的核心思想是只渲染当前视口内的元素以及少量缓冲区中的元素,而不是一次性将整个列表渲染到 DOM 中。通过监听滚动事件动态调整显示的内容,从而减少内存占用和重绘开销[^4]。 --- #### 实现步骤详解 以下是基于 Vue.js虚拟列表实现方法: 1. **初始化数据** 需要定义一些必要的变量,例如 `items`(数据源)、`itemHeight`(单个项目的高度)、`containerHeight`(容器总高度)等。 ```javascript const items = Array.from({ length: 1000 }, (_, i) => ({ id: i, name: `Item ${i}` })); ``` 2. **计算属性** 使用 Vue 的计算属性来推导出哪些项应该被渲染。这通常涉及以下几个参数: - `startIndex`: 当前视口中第一个可见项的索引。 - `endIndex`: 当前视口中最后一个可见项的索引。 - `scrollTop`: 容器的滚动偏移量。 计算逻辑如下所示: ```javascript computed: { visibleItems() { const start = Math.floor(this.scrollTop / this.itemHeight); const end = start + Math.ceil(this.containerHeight / this.itemHeight); return this.items.slice(start, end).map((item, index) => ({ ...item, offsetTop: (start + index) * this.itemHeight })); } } ``` 3. **模板部分** 在 HTML 模板中,仅需渲染那些处于可视区域范围内的条目即可。同时设置一个固定大小的占位符作为外部容器,以模拟完整的列表长度。 ```html <div class="virtual-list-container" :style="{ height: `${this.totalHeight}px`, overflowY: 'auto' }"> <ul> <li v-for="(item, index) in visibleItems" :key="index" :style="{ top: `${item.offsetTop}px` }">{{ item.name }}</li> </ul> </div> ``` 4. **处理滚动事件** 添加对滚动行为的支持,以便实时更新状态并触发重新计算过程。 ```javascript methods: { handleScroll(event) { this.scrollTop = event.target.scrollTop; }, updateContainerSize() { this.totalHeight = this.items.length * this.itemHeight; } }, mounted() { this.updateContainerSize(); window.addEventListener('resize', this.updateContainerSize); // 自适应窗口变化 }, beforeDestroy() { window.removeEventListener('resize', this.updateContainerSize); } ``` 5. **样式增强** 对外层容器施加 CSS 属性使其具备垂直方向上的滚动能力;内部子节点则利用绝对定位方式精确控制其位置分布情况。 ```css .virtual-list-container { position: relative; width: 100%; border: 1px solid #ccc; box-sizing: border-box; } ul { list-style-type: none; padding: 0; margin: 0; position: absolute; top: 0; left: 0; right: 0; } li { position: absolute; background-color: white; line-height: 50px; text-align: center; border-bottom: 1px solid gray; } ``` 以上即为一种典型的 Vue.js 下实现高效虚拟列表的方式。 --- #### 性能优势分析 相比传统全量渲染方案,此方法显著降低了浏览器端的压力,具体表现在以下方面: - 减少了实际挂载至 DOM 树上的节点数量; - 缩短了布局与绘制耗时; - 提升交互流畅度,尤其适用于移动端设备场景下。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值