Vue使用三方工具vueUse实现虚拟列表
作者:吃肉不吃皮
前言
书接上文,前篇文章介绍了如何手写一个虚拟列表,这篇文章就介绍一下如何偷懒使用现有的三方工具实现
vueUse方案实现
采用vueUse中的useVirtualList方法同样可以实现虚拟列表(相当于是使用一个封装好的方法)
步骤:
1.装包
npm i @vueuse/core
2.导入useVirtualList方法
如何使用?
在使用useVirtualList方法时需要传入两个参数,一个是数据源(就是你那十万条数据),一个是配置项(配置每项的高度)
在配置项中配置的高度一定要和模板中渲染的每一项的高度相同(即配置项的高度要与css中的高度保持一致)
这个方法返回三个字段,一个处理后的数据源,两个依赖项,这两个依赖项需要绑定到视图区域和占位盒子身上,从而实现虚拟列表的效果

手动添加类名,然后审查元素:
<template>
<div v-bind="containerProps" style="height: 500px" class="container">
<div v-bind="wrapperProps" class="slot">
<div v-for="item in list" :key="item.data.id" style="height: 40px">
Row: {{ item.data }}
</div>
</div>
</div>
</template>


大致的效果就是虚拟列表的div包裹着占位的div,占位的div内进行渲染。当然,样式自己就根据需要添加即可
完整代码
<script setup lang="ts">
import { useVirtualList } from '@vueuse/core'
import { onMounted, ref } from 'vue'
type Item = {
id: number
name: string
}
// 所有的数据,比如这个数组存放了十万条数据
const allListData = ref<Item[]>([])
// 获取十万条数据
const getData = () => {
for (let i = 0; i < 10000; i++) {
allListData.value.push({ name: `第${i}条数据`, id: i })
}
}
onMounted(() => {
getData()
})
const { list, containerProps, wrapperProps } = useVirtualList(allListData, {
// 此处配置的高度一定要和31行渲染时每一行的高度相同
itemHeight: 40
})
</script>
<template>
<div v-bind="containerProps" style="height: 500px" class="container">
<div v-bind="wrapperProps" class="slot">
<div v-for="item in list" :key="item.data.id" style="height: 40px">
Row: {{ item.data }}
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.container {
border: 1px solid black;
}
</style>
同时注意,将原始数据源传给useVirtualList之后返回的list是经过封装过的,想这里原本数据的每一项的结构是{ name:'', id:xx },经过处理后,再想访问name或者id,就得多访问一层data,即list.data.name / list.data.id
完整代码
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
type Item = {
id: number
name: string
}
// 所有的数据,比如这个数组存放了十万条数据
const allListData = ref<Item[]>([])
// 获取十万条数据
const getData = () => {
for (let i = 0; i < 10000; i++) {
allListData.value.push({ name: `第${i}条数据`, id: i })
}
}
onMounted(() => {
getData()
})
// 每一项的高度,比如 40 像素
const itemHeight = ref(40)
</script>
<template>
<RecycleScroller
class="viewport"
:items="allListData"
:item-size="itemHeight"
key-field="id"
v-slot="{ item }"
item-class="item"
>
{{ item.name }}
</RecycleScroller>
</template>
<style scoped lang="scss">
.viewport {
box-sizing: border-box;
width: 240px;
height: 400px;
border: solid 1px #000000;
// 开启滚动条
overflow-y: auto;
<!-- 由于模板中使用了 item-class 属性将渲染的每一项的类名改为 item,所以这里开启深层次的样式修改-->
:deep(.item) {
box-sizing: border-box;
width: 100%;
height: 40px; // 高度设置得和 item-size 属性的值一致。表示每一项的高度
display: flex;
justify-content: center;
align-items: center;
// 隔行变色
&:nth-child(even) {
background: skyblue;
}
&:nth-child(odd) {
background: red;
}
}
}
</style>
实现效果

审查一下元素:



其实可以发现底层实现原理和之前手写的部分差不多,都是最外层一个虚拟列表盒子,内层放置一个具有所有数据的高度的盒子,然后再设置一个视图层进行滚动。但是使用封装好的东西可以不用自己设置定位以及更新top值,而且其实它的文档里还有其他很多的属性和事件,拓展性强。还支持每一项的高度可以不同(可能在那种评论区用得多,毕竟每条评论的内容不一定都相同)
报错问题

由于使用的是 Vue3 + TS,所以在导入的时候会有类型报错,虽然不影响功能
尝试下载提示中的包文件,但是竟然显示找不到了,可能是在@types中没有这个包的声明文件吧

到此这篇关于Vue使用三方工具vueUse实现虚拟列表的文章就介绍到这了,更多相关Vue vueUse虚拟列表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
