vue js怎么实现列表滚动循环
更新时间:2023-11-24问题描述
在一些前端开发中,我们需要使用列表,有时候如果列表内容不多,直接使用静态列表即可。但是,有时候列表会非常长,甚至会无限加载,这个时候,列表就需要实现滚动循环,即快速滑动时能循环滚动列表,减少网络请求和渲染次数。
实现方式
列表滚动循环可以采用Vue.js编写,这里介绍一种基于Vue.js和element-ui的方式来实现。
实现步骤
1. 在Vue项目中引入element-ui组件库。
npm install element-ui -S
2. 在需要滚动的列表外层包裹容器,并为容器设置高度和 overflow 属性。
<div class="scroll-list" style="height: 400px;overflow: auto;">
<ul>
<li v-for="item in items" :key="item.id">{{item.name}}</li>
</ul>
</div>
3. 在 Vue 组件中,使用 computed 计算属性 splitItems 把列表分割成多个数组,并计算滚动高度scrollTop。splitItems 用于将每个item平均分割成固定数量的数组,scrollHeight 用于计算要滚动多少。
computed: {
splitItems () {
const chunkSize = 30 // 设置每个数组的长度,可自定义
return this.items.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index / chunkSize)
if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [] // 为每个数组创建一个子数组,初始为空
}
resultArray[chunkIndex].push(item) // 将item添加到子数组中
return resultArray
}, [])
},
scrollHeight () {
const perItemHeight = 40 // 设置每个item的高度,可自定义
return this.splitItems.length * perItemHeight
}
}
4. 在模板中分别使用计算结果,渲染出多个列表,同时根据滚动条滚动高度,切换显示列表。
<div class="scroll-list"
style="height: 400px;overflow: auto;"
@scroll="onScroll($event)">
<ul v-for="(chunk, index) in splitItems"
:key="index"
:style="{height: `${scrollHeight}px`,display: (showIndex === index ? 'block' : 'none')}`>
<li v-for="item in chunk" :key="item.id">
{{item.name}}
</li>
</ul>
</div>
5. 在 Vue methods 中实现 onScroll 方法,通过滚动高度获得当前应该显示的列表,更新 showIndex 即可。
methods: {
onScroll ({ scrollTop }) {
const perItemHeight = 40 // 设置每个item的高度,可自定义
const index = Math.floor(scrollTop / (perItemHeight * 30)) // 根据滚动高度和每个数组的长度计算出应该显示的列表
this.showIndex = index // 更新showIndex,切换显示列表
}
}
代码示例
下面是完整的代码实现:
<template>
<div class="scroll-list" style="height: 400px;overflow: auto;" @scroll="onScroll($event)">
<ul v-for="(chunk, index) in splitItems"
:key="index"
:style="{height: `${scrollHeight}px`,display: (showIndex === index ? 'block' : 'none')}`>
<li v-for="item in chunk" :key="item.id">
{{item.name}}
</li>
</ul>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data () {
return {
showIndex: 0
}
},
computed: {
...mapGetters(['items']),
splitItems () {
const chunkSize = 30
return this.items.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index / chunkSize)
if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = []
}
resultArray[chunkIndex].push(item)
return resultArray
}, [])
},
scrollHeight () {
const perItemHeight = 40
return this.splitItems.length * perItemHeight
}
},
methods: {
onScroll ({ scrollTop }) {
const perItemHeight = 40
const index = Math.floor(scrollTop / (perItemHeight * 30))
this.showIndex = index
}
}
}
</script>
<style scoped>
.scroll-list ul {
margin: 0;
padding: 0;
list-style-type: none;
}
.scroll-list ul li {
height: 40px;
line-height: 40px;
}
</style>