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

yizhihongxing

标题: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将后台数据时间戳转换成日期格式” 的完整攻略。 1. 确认后台数据时间戳格式 在进行时间戳转换之前,我们需要确保后台数据的时间戳格式是符合标准的。常见的时间戳格式有 Unix时间戳 和 ISO 8601时间戳。一般来说,Unix时间戳是一个整数,表示自1970年1月1日以来的秒数。而ISO 8601时间戳则是一个字符串,表示一种格式为…

    Vue 2023年5月28日
    00
  • 详解Vue中使用v-for语句抛出错误的解决方案

    下面是详解Vue中使用v-for语句抛出错误的解决方案的完整攻略。 问题描述 在Vue中使用v-for语句时,有时会出现以下错误: [Vue warn]: Error in render: "TypeError: Cannot read property ‘xxx’ of undefined" 这个错误通常发生在v-for语句循环数据时,…

    Vue 2023年5月27日
    00
  • 一篇超详细的Vue-Router手把手教程

    一篇超详细的Vue-Router手把手教程 简介 Vue-Router是Vue.js官方提供的用于路由管理的插件,可以帮助我们快速地构建单页应用。本文将从基础的使用开始,逐步深入解析Vue-Router的特性和使用方法,让你轻松掌握Vue-Router的使用。 基本使用 安装 使用npm安装Vue-Router: npm install vue-router…

    Vue 2023年5月27日
    00
  • vue.js父组件使用外部对象的方法示例

    下面是详细的攻略。 Vue.js父组件使用外部对象的方法示例 在Vue.js中,我们可以通过props(属性)将数据从父组件传递给子组件。同样地,如果你想在子组件中使用父组件中的方法,则需要使用事件来实现。 但是,有时候我们需要在父组件中使用子组件中的方法。这时候,我们需要使用$refs来访问子组件。当父组件渲染完成后,就可以通过$refs引用子组件并使用其…

    Vue 2023年5月28日
    00
  • vue自定义表单生成器form-create使用详解

    Vue自定义表单生成器form-create使用详解 1. 什么是form-create? form-create是一个基于Vue.js的自定义表单生成器。它可以根据预设的模板或者自定义的UI组件来动态生成表单,方便开发者快速构建各种表单,能够提高开发效率。 2. 如何使用form-create? 2.1 安装 首先,我们需要安装form-create,可以…

    Vue 2023年5月28日
    00
  • 详解关于element级联选择器数据回显问题

    关于Element级联选择器数据回显问题的攻略主要包含以下几个步骤: 在Vue组件中引入级联选择器<el-cascader>组件并设置必要的属性。 将级联选择器绑定到Vue组件中的data属性。 在级联选择器绑定的数组数据中搜索符合当前选项路径的数据并返回给级联选择器组件。 对于级联选择器组件中的onChange事件,更新选中的选项路径,将其保存…

    Vue 2023年5月29日
    00
  • vue-cli脚手架的安装教程图解

    下面是”vue-cli脚手架的安装教程图解”的完整攻略: 安装Node.js 首先,你应该安装Node.js。Node.js是一个JavaScript运行时环境,可以实现服务器端的JavaScript开发。 如果你还没有安装,可以从Node.js官网下载并安装:https://nodejs.org/ 安装vue-cli vue-cli是一个Vue.js项目的…

    Vue 2023年5月27日
    00
  • 浅谈vue项目,访问路径#号的问题

    对于“浅谈vue项目,访问路径#号的问题”,我将提供如下完整攻略: 1. 了解Hash模式路由 在讲解浅谈vue项目,访问路径#号的问题之前,首先需要了解Hash模式路由。所谓Hash模式,就是指Url中的锚点(#),它跟在URL后面的字符串。在使用Vue开发单页面应用时,Hash模式路由就是常用的路由模式。比如 VueRouter 就是这样的。 2. Vu…

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