js 滚动加载

该代码示例展示了如何在Vue.js应用中创建一个图片列表,当用户滚动到列表底部时,使用防抖(debounce)和节流(throttle)技术自动加载更多图片。通过监听滚动事件,判断滚动条位置并加载新内容,同时防止重复加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:图片等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>

滚动条样式可自定义

参数说明 listLoadingMore({id:"",id2:function(){},action:function(){},pageNum:10,getNew:undefined,funcArg:undefined,func:function(){},loadingMustTime:0,loadingDom:function(){},loadedDom:function(){},nullDataFunc:function(){},endFunc:function(){},errorFunc:function(){}}); id:滚动条id,不可以是body; id2:滚动列表的id,通过function自行根据情况返回; action:数据来源的ajax地址,插件会自动加上page和length(分别表示请求页数和当前已有记录数),返回格式统一是[{},{}...],此类jsonArray; ajaxType:ajax提交方式,将更改传递数据的方式,默认post; pageNum:每页加载数量,将会根据这个数量判断是否全部加载完成; getNew:自定义获取数据方法; funcArg:自定义获取数据时传递的参数,类型为函数,返回所需参数; childrenTag:列表子项的标签,默认LI; func:非自定义获取数据时,创建每行数据的方法; loadingMustTime:强制最小加载时间,默认0; loadingDom:加载中动画自定义,返回Dom或者HTML代码; loadedDom:完全加载完成动画自定义,返回Dom或者HTML代码; nullDataFunc:数据列表为空时执行的方法; endFunc:每页数据加载完成时执行的方法; errorFunc:ajax获取数据失败时调用的方法。 回调方法 调用本方法初始化后将会得到一个专属的方法集: Object {getNew:function,isFull:function,isRunning:function,isStop:function,loading:function,show:function}; getNew():忽略判断条件,强制执行加载操作。此时数据传递中,page值可能出错,但length值一定正确,请谨慎判断后在执行该方法; isFull(boolean):修改列表加载完成标志。true为全部加载完成,false则相反; isRunning(boolean):修改列表当前是否正在加载中标志。几乎没有使用的机会; isStop(boolean):设置是否停止加载,设置为true时将会阻止未来的所有加载操作; loading():根据当前滚动条的位置,自动判断是否需要加载新数据; show(boolean,boolean):强制设置加载中和加载完成dom的显示或隐藏,true表示显示,false相对。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值