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

目录
  • 前言
  • 实现原理
  • 实现代码
  • 总结

前言

应用场景:后台一次性发送上千条或更多数据给前台

场景模拟:用户发起一个请求,后台发送了10w条数据

使用虚拟列表之前:前台需要生成10w个dom节点用来渲染页面

使用虚拟列表之后:前台只需要生成少量dom节点(dom节点数量取决于前端视图需要展示的数量),就可以实现对这10w条数据的视图渲染

总之:虚拟列表就是固定dom节点数量,通过修改dom节点的内容而达到不重新增加(或删除)dom节点来实现列表的更新

实现原理

  • 监听页面滚动,获取滚动的高度scrolltop
  • 根据scrolltop,可以知道当前应该展示哪一段数据(即获取要展示数据的index)
  • 根据当前展示的数据在长列表中的index,对列表进行偏移

实现思路是这样的:

设置列表初始值

  1. 需要展示给用户的数量showNum
  2. 列表item的高度itemHeight
  3. 需要展示的第一条数据的下标start
  4. 需要展示的最后一条数据的下标end
  5. 通过start和end已经showNum,我们可以得到需要展示的列表项showList,我们可以通过vue的计算属性来实时获取新的showList

建立列表视图模型

  • 给列表视图设置高度ListWrapHeight
  • 根据itemHeightshowNum,我们可以得到列表总高度ListHeight,我们必须要使得ListHeight高度大于ListWrapHeight,这样才能实现滚动

监听页面滚动

  • 给列表视图模型设置监听函数,每当列表视图发生滚动,就执行回调,获取滚动高度scrolltop
  • 通过scrolltop和itemHeight我们可以得到新的start以及end,从而获取到新的showList
  • 通过start和itemHeight我们可以给list设置偏移(translate),从而达到让start对应的数据展示在视图模型的效果

注意:列表视图模型和列表并不是一个东西,视图模型表示者页面供列表展示的一块区域,而列表表示的是需要展示的列表项总高度

这是列表视图模型

这是列表

列表中超出视图模型的节点就被隐藏了

为什么限制了展示列表项的长度(限制了dom数量),视图模型还能持续滚动?

给列表设置translate会增大列表的高度,既然list的高度变大了,那么视图模型就可以继续滚动

实现代码

​ 以vue3为例(不管是vue2或是vue3,实现虚拟列表的核心代码都是相同的,即监听滚动,赋新值)

<div ref="listWrap" class="list-wrap" @scroll="scrollListener">
    <div class="list" ref="List">
        <slot  v-for="item in showList" :songInfo="item" :key="item.id"></slot>
    </div>
  </div>
  setup(props) {
    const list = ref(props.list); //长列表数据
    const itemHeight = ref(props.itemHeight); //item高度
    const showNum = ref(props.showNum); //展示的数据
    const start = ref(props.start); //滚动过程中的开始索引
    const end = ref(props.end); //滚动过程中的结束索引
    const listWrap = ref(null); //获取列表视图模型节点
    const List = ref(null)//获取列表节点
    onMounted(() => {
        listWrap.value.style.height = itemHeight.value * showNum.value + "px";//设置列表视图模型的高度
    });
    const showList = computed(() => {
      //获取展示的列表
      return list.value.slice(start.value, end.value);
    });

    const scrollListener = (() => {
           //获取滚动高度
            let scrollTop = listWrap.value.scrollTop;
            //开始的数组索引
            start.value = Math.floor(scrollTop / itemHeight.value);
            //结束索引
            end.value = start.value + showNum.value;
            List.value.style.transform =  `translateY(${start.value * itemHeight.value}px)`//对列表项进行偏移
    })
    return {
      ...
    };
  },

效果:

节点变化

可以看到不论列表如何变化,列表dom的数量并没有新增

总结

到此这篇关于vue长列表优化之虚拟列表实现的文章就介绍到这了,更多相关vue虚拟列表实现内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue实现虚拟列表组件解决长列表性能问题

    目录 一.虚拟列表 二.实现思路 难点与思考: 其他注意事项: 三.实现 最终实现效果 实现代码 模拟数据的后端代码 四.封装为组件 props: event: 虚拟列表组件代码 使用代码 最近项目中需要用到列表的展示,且不分页.当数据加载太多时会造成性能问题.因此采用虚拟列表来优化 一.虚拟列表 真实列表:每条数据都展示到html上,数据越多,DOM元素也就越多,性能也就越差. 虚拟列表:只展示部分数据(可见区域展示数据),当屏幕滚动时替换展示的数据,DOM元素的数量是固定的,相比较真实列表更

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

    目录 前言 实现原理 实现代码 总结 前言 应用场景:后台一次性发送上千条或更多数据给前台 场景模拟:用户发起一个请求,后台发送了10w条数据 使用虚拟列表之前:前台需要生成10w个dom节点用来渲染页面 使用虚拟列表之后:前台只需要生成少量dom节点(dom节点数量取决于前端视图需要展示的数量),就可以实现对这10w条数据的视图渲染 总之:虚拟列表就是固定dom节点数量,通过修改dom节点的内容而达到不重新增加(或删除)dom节点来实现列表的更新 实现原理 监听页面滚动,获取滚动的高度scro

  • 对Python3中列表乘以某一个数的示例详解

    在Python列表操作中:列表乘以某一个数,如list2 = list1 * 2 得到一个新的列表是list1的元素重复n次,且list1不改变. 但运行如下代码时,得到的新列表b中,b[0]和b[1]的地址相同,即对b[0]进行操作,b[1]也会发生改变. a = [0] b = [a] * 2 print(b) b[0].append(1) print(b) 输出为: [[0], [0]] [[0, 1], [0, 1]] 随后尝试以下几种代码: 代码(1) a = [0] b = [a f

  • 对python列表里的字典元素去重方法详解

    如下所示: def list_dict_duplicate_removal(): data_list = [{"a": "123", "b": "321"}, {"a": "123", "b": "321"}, {"b": "321", "a": "123"}] run

  • Vue3 如何通过虚拟DOM更新页面详解

    目录 引言 Vue 虚拟 DOM 执行流程 DOM 的创建 patch 函数 patchElement 函数 节点自身属性的更新 子元素的更新 patchChildren 位运算 为什么位运算性能更好 如何运用位运算 最长递增子系列 贪心 + 二分 引言 上一讲我们主要介绍了 Vue 项目的首次渲染流程,在 mountComponent 中注册了effect 函数,这样,在组件数据有更新的时候,就会通知到组件的 update 方法进行更新 Vue 中组件更新的方式也是使用了响应式 + 虚拟 DO

  • vue iview组件表格 render函数的使用方法详解

    如果要在标签中加入属性,例如img 中src属性   a标签中href属性  此时需要用到 attrs 来加入而不是props { title: '操作', key: 'action', align: 'center', render: function (h, params) { return h('div', [ h('Button', { props: { type: 'primary', size: 'small' }, style: { marginRight: '8px' }, on

  • Vue一个案例引发的递归组件的使用详解

    今天我们继续使用 Vue 的撸我们的实战项目,只有在实战中我们才会领悟更多,光纸上谈兵然并卵,继上篇我们的 <Vue一个案例引发的动态组件与全局事件绑定总结> 之后,今天来聊一聊我们如何在项目中使用递归组件. 信息的分类展示列表 这次我们主要是实现一个信息的分类展示列表存在二级/三级的分类,如下如所示: 看到这个很多人会想到这个实现起来很简单啊,来个嵌套循环不就完事了. 对,你说的没错,事实就是这样简单.那么就先来看看这么简单的列表怎么实现的,然后这个方案的劣势在哪里. 首先看看我们的数据格式

  • vue.js2.0 实现better-scroll的滚动效果实例详解

    什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在这里 .better-scroll 也很强大,不仅可以做普通的滚动列表,还可以做轮播图.picker 等等. <template> <div> <div class="goods"> <div class="menu-wrapper" ref="menuWr

  • vue 中动态绑定class 和 style的方法代码详解

    先列举一些例子 class="['content',{'radioModel':checkType}]" class="['siteAppListDirNode',{open:appitem.open==true}]" class="['portalCenterMenu',{showNav:!showHideNav,hideNav:showHideNav}]" class="{shortcutMenuShow:!showHideNav,

  • vue+element树组件 实现树懒加载的过程详解

    一.页面样式 二.数据库 三.前端页面代码 <template> <el-tree :props="props" :load="loadNode" lazy show-checkbox> </el-tree> </template> <script> export default { data () { return { props: { label: 'name', children: 'zones',

  • python优化数据预处理方法Pandas pipe详解

    我们知道现实中的数据通常是杂乱无章的,需要大量的预处理才能使用.Pandas 是应用最广泛的数据分析和处理库之一,它提供了多种对原始数据进行预处理的方法. import numpy as np import pandas as pd df = pd.DataFrame({ "id": [100, 100, 101, 102, 103, 104, 105, 106], "A": [1, 2, 3, 4, 5, 2, np.nan, 5], "B":

随机推荐