js 滚动加载

场景:图片等list样式的内容,需要在不翻页的情况下使用加载更多。

方式:页面或div的滚动条滚动到底部或者特定位置后,自动加载更多内容

代码实现

<template>
  <div ref="imageList" v-loading="loading" class="image-list">
    <div slot="add" class="image-box">
      <i class="el-icon-picture-outline" />
      自定义上传...
    </div>
    <div v-for="image in images" :key="image.id" class="image-box">
      <img :src="image.url" :alt="image.description" style="width: 100%;">
    </div>
  </div>
</template>

<script>
import { picture } from '@/APIS/common'

import { debounce, throttle } from 'lodash' // import debounce and throttle functions from Lodash library

export default {
  props: {
    pictype: {
      type: String,
      default: 'background'
    }
  },
  data() {
    return {
      images: [], // array to store loaded images
      loading: false, // flag to prevent loading duplicate images
      page: 1, // current page number
      perPage: 10, // number of images to load per page
      imageListRef: null, // reference to the image list element
      height: 0, // 图片列表总高度
      total_num: 0 // 图片总数
    }
  },

  mounted() {
    this.imageListRef = this.$refs.imageList

    this.height = this.imageListRef.scrollHeight
    // this.imageListRef.clientHeight + this.imageListRef.scrollTop >= this.height

    // add scroll event listener to the image list
    this.imageListRef?.addEventListener('scroll', this.handleScrollDebounced)

    // 加载图片
    this.loadImages() // load initial set of images
  },
  beforeDestroy() {
    this.imageListRef?.removeEventListener('scroll', this.handleScrollDebounced) // remove debounced scroll event listener
  },
  methods: {
    async loadImages() {
      if (this.loading) return // prevent loading duplicate images
      // 判断总数 是否加载完全
      if (this.total_num && this.images.length >= this.total_num) {
        return
      }
      const size = this.height / 230 * 3
      // 向上取整
      const nums = Math.ceil(size)
      this.loading = true // set loading flag
      const response = await picture({
        page_id: this.page,
        num_per_page: this.page === 1 ? (nums + 1) : 6,
        enable: 1,
        type: this.pictype
      })

      if (response.code === 0) {
        const newImages = await response.data.list
        this.total_num = response.data.total_num
        this.images = [...this.images, ...newImages] // append new images to existing array
        this.loading = false // clear loading flag
        this.page++ // increment page number for next load

        // height 需要计算 images
        this.height = Math.ceil(this.images.length / 3) * 230
      } else {
        this.$message.error(response.msg || '加载失败')
      }
    },
    handleScrollThrottled: throttle(function() {
      if (this.imageListRef.clientHeight + this.imageListRef.scrollTop >= this.height) {
        this.loadImages() // trigger loading of new images when user has scrolled to the bottom
      }
    }, 300), // set a minimum interval of 300ms between function calls
    handleScrollDebounced: debounce(function() {
      this.handleScrollThrottled() // delay the execution of the throttled function by 300ms
    }, 300)
  }
}
</script>

<style lang="scss" scoped>
.image-list {
  padding: 0 8px;
  display: flex;
  flex-wrap: wrap;
  justify-content: start;
  align-items: flex-start;
  height: 100vh;
  /* set the height of the component to the height of the viewport */
  width: 440px;
  overflow: auto;

  &::-webkit-scrollbar {
    width: 4px;
    // height: 10px;
  }

  &::-webkit-scrollbar-thumb {
    background-color: #B1B1B1;
    border-radius: 4px;
    height: 10px;
  }
}

.image-box {
  width: 129px;
  height: 230px;
  cursor: pointer;
  margin: 5px;
  img {
    border-radius: 6px;
  }
}
</style>

滚动条样式可自定义

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值