c语言编程笔录

首页 >   > 笔记大全

笔记大全

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>