vue长列表优化之虚拟列表实现过程详解

标题:Vue长列表优化之虚拟列表实现过程详解

1. 前言

在处理Vue中长列表(包含大量子组件)时,当数据更新时,会造成较大的性能问题。因此,为了提高Vue应用的性能,我们通常会做一些长列表的优化。其中,虚拟列表技术是一种高效的长列表优化方法。本文旨在介绍Vue中如何利用虚拟列表技术实现长列表优化。

2. 虚拟列表实现过程详解

2.1 什么是虚拟列表

虚拟列表是指只渲染当前滚动区域内的子组件,而不是全部渲染。当用户滚动列表时,只有当前可见区域内的列表项才会被渲染,同时被滚动到可见区域外的列表项则会被销毁。这种做法不仅能够提高列表的渲染性能,同时也能够节省内存空间。

2.2 实现过程

2.2.1 计算总高度

虚拟列表的实现需要先计算出列表项总高度,以便后续做一些计算处理。

mounted() {
  // 计算每个列表项高度
  this.itemHeight = this.$refs.item[0].clientHeight
  // 计算列表总高度
  this.totalHeight = this.itemHeight * this.list.length
}

2.2.2 计算显示区域

然后我们需要计算出当前屏幕可见区域内的列表项。我们可以通过计算可视区域内第一项的索引来实现。

watch: {
  scrollTop(newVal) {
    this.start = Math.floor(newVal / this.itemHeight)
    // 为了避免底部区域不足一个完整的列表项高度而导致渲染的列表项不完整,需向下取整
    this.end = Math.ceil((newVal + this.visibleHeight) / this.itemHeight)
  }
}

2.2.3 渲染虚拟列表

接下来是实现虚拟列表的关键步骤,即在计算出显示区域后,只渲染这些显示区域内的列表项。为了实现这个目的,我们需要在模板中加入一个用来展示虚拟列表项的容器,然后根据计算出的start和end索引,只渲染这些需要展示的列表项。

<template>
  <div class="list-container" ref="listContainer" @scroll="onScroll">
    <div class="virtual-list" :style="{height: totalHeight + 'px', paddingTop: start * itemHeight + 'px', paddingBottom: (list.length - end) * itemHeight + 'px'}">
      <div class="item" v-for="(item, index) in list" :key="index" :ref="'item-' + index" :style="{top: index * itemHeight + 'px'}" v-show="index >= start && index < end">
        {{item}}
      </div>
    </div>
  </div>
</template>

关键部分是"v-show"指令,根据计算出的"start"和"end"索引,只渲染当前显示区域内的列表项。

3. 示例说明

3.1 示例1

实现一个包含10000个列表项的虚拟列表组件。其中,每个列表项是一个文本框,用户可以在里面输入内容。在用户在文本框中输入内容时,控制台将输出当前列表项的内容。

<template>
  <div class="list-container" ref="listContainer" @scroll="onScroll">
    <div class="virtual-list" :style="{height: totalHeight + 'px', paddingTop: start * itemHeight + 'px', paddingBottom: (list.length - end) * itemHeight + 'px'}">
      <div class="item" v-for="(item, index) in list" :key="index" :ref="'item-' + index" :style="{top: index * itemHeight + 'px'}" v-show="index >= start && index < end">
        <input type="text" placeholder="请输入内容" v-model="item" @input="onInput(index)">
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [],
      itemHeight: 40,
      visibleHeight: 500 // 可视区域高度
    }
  },
  mounted() {
    this.initList()
  },
  methods: {
    initList() {
      // 初始化列表数据
      for (let i = 0; i < 10000; i++) {
        this.list.push('item' + i)
      }
      // 计算每个列表项高度
      this.itemHeight = this.$refs.item[0].clientHeight
      // 计算列表总高度
      this.totalHeight = this.itemHeight * this.list.length
    },
    onScroll() {
      // 计算当前可见区域的索引
      this.start = Math.floor(this.$refs.listContainer.scrollTop / this.itemHeight)
      this.end = Math.ceil((this.$refs.listContainer.scrollTop + this.visibleHeight) / this.itemHeight)
    },
    onInput(index) {
      // 输出列表项内容
      console.log(this.list[index])
    }
  }
}
</script>

此示例中,列表项使用input标签来展示,用户在输入内容时,控制台将输出当前列表项的内容。

3.2 示例2

实现一个包含100个图片的虚拟列表组件。其中,每个列表项是一个图片容器。当用户滚动列表时,用随机生成的颜色来填充图片,并展示在列表项中。

<template>
  <div class="list-container" ref="listContainer" @scroll="onScroll">
    <div class="virtual-list" :style="{height: totalHeight + 'px', paddingTop: start * itemHeight + 'px', paddingBottom: (list.length - end) * itemHeight + 'px'}">
      <div class="item" v-for="(item, index) in list" :key="index" :ref="'item-' + index" :style="{top: index * itemHeight + 'px'}" v-show="index >= start && index < end">
        <div class="img-container">
          <div class="img" :style="{backgroundColor: item.color}"></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [],
      itemHeight: 300,
      visibleHeight: 500 // 可视区域高度
    }
  },
  mounted() {
    this.initList()
  },
  methods: {
    initList() {
      // 初始化列表数据
      for (let i = 0; i < 100; i++) {
        this.list.push({color: this.getRandomColor()})
      }
      // 计算每个列表项高度
      this.itemHeight = this.$refs.item[0].clientHeight
      // 计算列表总高度
      this.totalHeight = this.itemHeight * this.list.length
    },
    onScroll() {
      // 计算当前可见区域的索引
      this.start = Math.floor(this.$refs.listContainer.scrollTop / this.itemHeight)
      this.end = Math.ceil((this.$refs.listContainer.scrollTop + this.visibleHeight) / this.itemHeight)

      // 更新列表项颜色,随机生成
      for (let i = this.start; i < this.end; i++) {
        this.$set(this.list[i], 'color', this.getRandomColor())
      }
    },
    getRandomColor() {
      // 生成随机颜色
      return '#' + Math.floor(Math.random() * 16777215).toString(16)
    }
  }
}
</script>

此示例中,列表项为图片容器,当用户滚动列表时,随机生成一个颜色来渲染图片,并展示在列表项中。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue长列表优化之虚拟列表实现过程详解 - Python技术站

(0)
上一篇 2023年5月29日
下一篇 2023年5月29日

相关文章

  • 超详细的vue组件间通信总结

    既然你想了解“超详细的vue组件间通信总结”的完整攻略,那我来跟你讲解一下。 首先,我们需要知道,在Vue中,组件的通讯是非常关键的,特别是当应用变得越来越大,你需要找到一种有序、快速、可维护的方式来传递数据和事件。为此,Vue提供了几种用于处理通讯的方案。 Vue组件间通信方式主要包括下面这些: 父组件向子组件传递数据 子组件向父组件传递数据 使用Even…

    Vue 2023年5月27日
    00
  • vue中如何进行异步请求

    当在Vue.js应用程序中进行异步请求时,Vue.js使我们能够使用它在“vue-resource”和“axios”两个包中提供的两种不同方式。这两种方式都可以很容易地在Vue.js中创建和使用XHR请求。现在,我们来看一下如何使用这两种方式进行异步请求。 使用vue-resource进行异步请求 步骤一:安装vue-resource 在Vue.js项目中使…

    Vue 2023年5月29日
    00
  • vuex实现及简略解析(小结)

    Vuex实现及简略解析 Vuex是一个专为Vue.js设计的状态管理库,他采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。在大型的Vue.js应用程序中,多个组件之间共享同一状态,直接进行状态传递会比较麻烦。在这种情况下,我们可以使用Vuex。本文详细介绍了Vuex的实现和简略的解析。 Vuex简单介绍 Vuex提供…

    Vue 2023年5月28日
    00
  • Vue3使用路由及配置vite.alias简化导入写法的过程详解

    下面就来详细讲解一下“Vue3使用路由及配置vite.alias简化导入写法的过程详解”。 一、前置准备 在开始使用路由及配置vite.alias之前,需要先安装Vue3及Vue Router。使用命令行工具安装: npm install vue@next vue-router@4 –save 同时,还需要使用Vite作为打包工具。同样使用命令行工具安装:…

    Vue 2023年5月28日
    00
  • vue计算属性computed、事件、监听器watch的使用讲解

    下面我将详细讲解“vue计算属性computed、事件、监听器watch的使用讲解”的完整攻略,让你更加深入理解vue中这三个重要的概念。 计算属性computed computed可以理解为计算属性,它可以根据已经存在的数据computed属性(即model中data中的属性)进行计算得到一个新的值,这个新的值可以使用在模板中。computed具有缓存的特…

    Vue 2023年5月28日
    00
  • vue 组件高级用法实例详解

    以下是详细的“vue 组件高级用法实例详解”的攻略。 1. 简介 Vue 组件是 Vue.js 应用的基本构建块,可以将应用程序划分为一些小的、独立的,可复用的代码块,从而让代码更加高效、便于维护。 然而,Vue 组件并不仅仅是简单的模板和数据的组合。在这篇指南中,我们将介绍 Vue 组件的一些高级用法,帮助你更深入而全面地了解这个基本的概念。 2. 组件高…

    Vue 2023年5月28日
    00
  • 深入理解vue.js中$watch的oldvalue与newValue

    深入理解vue.js中$watch的oldValue与newValue 在Vue.js中,$watch是一个非常核心的API,经常用来监听数据的变化。$watch的主要用法如下: watch: { ‘data.field'(newVal, oldVal) { // 当 data.field 发生变化时触发该回调函数,newVal 表示变化后的值,oldVal…

    Vue 2023年5月28日
    00
  • vue2.0 自定义组件的方法(vue组件的封装)

    下面我将详细讲解“vue2.0 自定义组件的方法(vue组件的封装)”的完整攻略。 1. vue组件的封装 Vue是一个组件化开发的框架,在实际开发中,我们常常需要将一些通用的功能封装成组件,以方便复用。Vue中封装组件的方法主要有两种: 全局组件:在Vue的实例中注册一个全局组件,可以在全局范围内使用; 局部组件:在Vue组件中定义局部组件,只能在该组件内…

    Vue 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部