vue虚拟化列表封装的实现

 更新时间:2022年06月06日 09:21:46   作者:郭俊强  
这篇文章主要介绍了vue实现虚拟化列表封装方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

vue虚拟化列表封装

将下面代码复制一份到自己的项目中 

<template>
    <div class="scrollParent" ref="scrollContent" @scroll="handleScroll">
        <div :style="blankFillStyle">
            <div v-for="item,index in showDataList" :key="index">
                <slot :everyVirtual="item"></slot>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    props:["oneHeight","virtualList"],
    data () {
        return {
            contentSize:"", //可视区域可以展示多少条数据
            startIndex:0, //记录当前滚动的第一个元素的索引
            currentScroll:0,  //记录当前滚动的距离
        }
    },
    methods:{
        // 获取可视区域可以展示多少条
        getContentSize(){
            // 两次取反可以获取到整数部分
            this.contentSize = ~~(this.$refs.scrollContent.offsetHeight / this.oneHeight) + 2;
        },
        // 监听滚动条
        handleScroll(){
            // 持续滚动  减少变量重新赋值  优化处理 只有在到下一个元素节点的时候才会重新给this.statrIndex赋值  避免和this.startIndex相关联的数据再次计算
            this.currentScroll = this.$refs.scrollContent.scrollTop;
            let currentIndex = ~~(this.$refs.scrollContent.scrollTop/this.oneHeight);
            if(this.startIndex == currentIndex){
                return
            }
            this.startIndex = currentIndex;
            if((this.startIndex + this.contentSize - 1)>this.virtualList.length-1){ //说明到达底部了
                this.$emit("scrollEnd")
            }
        }
    },
    activated(){
        this.$nextTick(()=>{
            this.$refs.scrollContent.scrollTop = this.currentScroll;
        })
    },
    computed:{
        endIndex(){ //获取最后一个元素的索引
            let endIndex = this.startIndex + this.contentSize*2;
            if(endIndex>this.virtualList.length-1){
                endIndex = this.virtualList.length-1
            }
            return endIndex;
        },
        showDataList(){
            let startIndex = 0;
            if(this.startIndex<=this.contentSize){
                startIndex = 0;
            }else{
                startIndex = this.startIndex - this.contentSize;
            }
            return this.virtualList.slice(startIndex,this.endIndex);
        },
        blankFillStyle(){
            let startIndex = 0;
            if(this.startIndex<=this.contentSize){
                startIndex = 0;
            }else{
                startIndex = this.startIndex - this.contentSize;
            }
            return{
                paddingTop:startIndex * this.oneHeight + "px",
                paddingBottom:(this.virtualList.length - this.endIndex) * this.oneHeight +"px"
            }
        }
    },
    mounted(){
        window.onresize = this.getContentSize();
        window.orientationchange = this.getContentSize();
    }
}
</script>
<style scoped>
    .scrollParent{
        height: 100%;
        width: 100%;
        overflow-y: auto;
    }
</style>

vue虚拟列表-vue-virtual-scroll-list

使用场景

因为公司做了类似于百度网盘的竞品,所以用户如果上传了很多的文件,就会造成页面DOM元素的过多,然后因为需要操作DOM元素,所以页面会变得很卡。所以用虚拟列表来解决。

安装

安装的话这个插件有2个版本的,一个是1版本,目前更新到2版本了,二版本功能更加的强大。这里使用了1版本,通俗易懂一点。

npm install --save vue-virtual-scroll-list@1.1.3

使用

在单页面中导入

import VirtualList from "vue-virtual-scroll-list";
components: {
    VirtualList,//注册组件
  },
          <div class="content-timeview_box">
            <!-- size代表行高 remain代表一次渲染的数量 -->
            <!-- 出现的问题:1.在时间视图时(文件夹视图只有一个VirtualList不受影响) 一个日期代表一个VirtualList 怎么解决高度问题? -->
            <!-- 如果统一高度?一个日期中的文件数量少于高度 就会出现VirtualList之间的空白问题 -->
            <!-- 应该根据日期下的文件数量来动态的绑定每一个VirtualList的高度 -->
          <VirtualList
          :size="40"
          :remain="17" 
          :wclass="vuesrollboxviewClass"
          :tobottom="toBottom"
          style="padding: 0 32px 0 32px"
          :style="{height:itembig.items.length>6?scrollbarheight:'200px'}"
        >
  • toBottom的方法,这个地方就很坑,因为我只能在1.1.3版本中触发这个方法,1版本的其他版本号我没有触发成功,应该还是高度的问题。
  • toBottom:滚动到底部时触发,请求下一组数据
    //滚到底部时触发
    //注:此方法在1.0高版本不兼容,只能在官方文档1.1.3版本中使用
    //@1.1.3
    toBottom() {
      this.infiniteHandler();
    },
:wclass=“vuesrollboxviewClass”

wclass是自定义的class,我这里的业务场景不是每行只有1个数据,从上而下排列下来,而是每行根据分辨率不同,展示5个或6个,所以得计算好一次渲染的个数,需要动态的绑定。

小结:还是需要更熟练的掌握原生JS,虽然有各种各样的框架插件来解决问题,但是碰到业务场景更复杂的时候呢?所以还是要掌握原生JS,具备自己写轮子的能力才行。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。 

相关文章

  • vue中利用prop进行父子通信时的注意事项总结

    vue中利用prop进行父子通信时的注意事项总结

    这篇文章主要给大家介绍了关于vue中利用prop进行父子通信时的注意事项,文中通过实例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-01-01
  • 前端vue如何监听对象或者数组某个属性的变化详解

    前端vue如何监听对象或者数组某个属性的变化详解

    这篇文章主要给大家介绍了关于前端vue如何监听对象或者数组某个属性的变化的相关资料,在Vue中你可以使用watch或者computed来监听对象或数组某个属性的变化,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • vue3中watch和watchEffect实战梳理

    vue3中watch和watchEffect实战梳理

    这篇文章主要介绍了vue3中watch和watchEffect实战梳理,watch和watchEffect都是vue3中的监听器,但是在写法和使用上是有区别的。下文介绍他们之间的方法及区别,需要的朋友可以参考一下
    2022-07-07
  • vue子路由跳转实现tab选项卡效果

    vue子路由跳转实现tab选项卡效果

    这篇文章主要为大家详细介绍了vue子路由跳转实现tab选项卡效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 如何使用 vxe-table 将行数据标记为删除状态

    如何使用 vxe-table 将行数据标记为删除状态

    vxe-table支持将数据标记为待删除状态,通过调用setPendingRow方法,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • 你了解vue3.0响应式数据怎么实现吗

    你了解vue3.0响应式数据怎么实现吗

    这篇文章主要介绍了你了解vue3.0响应式数据怎么实现吗,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • Vue中非父子组件通信的方法小结

    Vue中非父子组件通信的方法小结

    在Vue.js中,组件间的通信是构建复杂应用的关键,但当涉及到非父子关系的组件通信时,传统的做法就显得力不从心了,本文将深入探讨几种有效的非父子组件通信方法,并通过具体的代码示例来帮助读者理解和应用这些技术,需要的朋友可以参考下
    2024-09-09
  • vue中使用echarts以及简单关系图的点击事件方式

    vue中使用echarts以及简单关系图的点击事件方式

    这篇文章主要介绍了vue中使用echarts以及简单关系图的点击事件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • vue3+ts封装弹窗及封装分页的示例代码

    vue3+ts封装弹窗及封装分页的示例代码

    这篇文章主要介绍了vue3+ts封装弹窗及封装分页的示例代码,本文通过定义defaultDialog .vue,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • vue3中v-for报错'item'is of type'unknown'的解决方法

    vue3中v-for报错'item'is of type'unknown'的

    在写vue3+ts的项目,得到一个数组,需要循环展示,使用v-for循环,写完之后发现有个报错,接下来通过本文给大家介绍vue3中v-for报错 ‘item‘ is of type ‘unknown‘的解决方法,感兴趣的朋友一起看看吧
    2023-11-11

最新评论