Vue 中如何实现滚动加载图片或列表?

1. 什么是滚动加载?

滚动加载也被称为无限滚动,是一种用户体验优化技术,可以在用户滚动查看内容时,动态向页面加载更多的数据,而不需要用户手动点击“加载更多”等按钮。

滚动加载通常用于处理包含大量数据的列表、图片等情况,通过在需要的时候批量加载数据,可以提高页面加载效率、优化用户体验。

2. Vue 中如何实现滚动加载?

2.1 监听滚动事件

在 Vue 中实现滚动加载,首先要做的就是监听页面滚动事件。可以通过在指令中监听滚动事件,或者在组件中通过添加事件监听器来实现。

下面是指令实现滚动事件监听的示例代码:


Vue.directive('scroll', {
  bind: function (el, bind, vnode) {
    el.addEventListener('scroll', function () {
      // 这里触发滚动事件后的回调函数
    })
  }
})

通过在元素上绑定指令 'v-scroll',并在指令的生命周期钩子 bind 中添加滚动事件监听器,就可以监听到元素的滚动事件了。

2.2 判断是否需要加载新数据

在监听到滚动事件后,接下来要做的就是判断当前页面是否需要加载新数据。一般来说,可以通过判断页面滚动位置和页面总高度等信息,来判断是否接近页面底部、是否需要继续加载数据。

下面是示例代码:


Vue.directive('scroll', {
  bind: function (el, bind, vnode) {
    el.addEventListener('scroll', function () {
      if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {
        // 这里判断是否接近页面底部
      }
    })
  }
})

在判断页面是否需要加载数据时,可以根据自己的需求来调整判断条件。例如上面的代码中,当页面滚动到倒数第 50px 时,就开始请求新的数据。

2.3 请求新的数据

当判断当前页面需要加载新数据时,接下来就是请求新的数据,并更新页面的渲染结果了。这里需要注意,请求新的数据可能会涉及到异步加载和数据处理,需要在异步加载完成后再更新页面。

下面是示例代码:


Vue.directive('scroll', {
  bind: function (el, bind, vnode) {
    el.addEventListener('scroll', function () {
      if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {
        // 请求新的数据
        // ...
        // 更新页面渲染结果
        // ...
      }
    })
  }
})

这里的请求新数据和更新页面渲染结果,具体实现方式会根据不同的需求而有所不同。例如我们可以使用 Axios 发送 Ajax 请求,根据返回结果更新数据。对于列表型数据,我们可以使用数组 push 方法添加新的数据。

2.4 防止多次触发加载

实现滚动加载时,有一个常见的问题就是会重复触发加载事件,导致多次请求相同的数据,从而影响用户体验。

为了避免这种情况,可以通过设置一个标志位,记录当前是否正在加载中。如果正在加载中,就不再触发新的加载事件,等到上一个请求完成后再进行下一个请求。

下面是示例代码:


Vue.directive('scroll', {
  bind: function (el, bind, vnode) {
    var isLoading = false
    el.addEventListener('scroll', function () {
      if (isLoading) {
        return
      }
      if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {
        isLoading = true
        // 请求新的数据
        // ...
        axios.get('/api/data').then(function (data) {
          // 更新页面渲染结果
          // ...
          isLoading = false
        })
      }
    })
  }
})

这里使用 isLoading 标志位来记录当前是否正在加载中。在触发新的加载事件时,如果 isLoading 为 true,就直接返回,不再触发新的请求;否则就进行请求,并在请求完成后将 isLoading 设为 false。

3. 滚动加载图片示例

下面是一个使用 Vue 实现滚动加载图片的示例。当滚动到页面底部时,会从 API 中请求新的图片,并在页面上展示。


<template>
  <div class="container" v-scroll="loadMore">
    <div class="list">
      <div class="item" v-for="item in items" :key="item.id">
        <img :src="item.url">
      </div>
    </div>
    <div v-if="loading" class="loading">Loading...</div>
  </div>
</template>
<script>
import axios from 'axios'
export default {
  data () {
    return {
      page: 1,
      items: [],
      loading: false
    }
  },
  methods: {
    loadMore () {
      if (this.loading) return
      const el = this.$el.querySelector('.list')
      if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {
        this.loading = true
        axios.get('https://picsum.photos/v2/list?page=' + this.page)
          .then(res => {
            this.items.push(...res.data)
            this.page++
            this.loading = false
          })
      }
    }
  }
}
</script>

在上面的示例中,使用指令 'v-scroll' 监听滚动事件,并在事件处理函数 loadMore 中请求新的图片,更新页面渲染结果。同时使用 loading 标志位来防止多次触发加载事件。

4. 小结

滚动加载是一种优化用户体验、提升页面性能的常见方法,Vue 作为一款主流的前端框架,自然也可以很容易地实现滚动加载功能。通过监听滚动事件、判断是否需要加载新数据、请求新的数据,并防止多次触发加载,就可以轻松实现滚动加载。