前言
在现代 Web 开发中,瀑布流布局因其视觉吸引力和高效的屏幕空间利用率而广受欢迎。Vue3 作为前端开发的热门框架,提供了丰富的工具和插件来实现各种复杂的 UI 效果。今天,我们就来探讨如何在 Vue3 项目中实现一个滚动分页加载的瀑布流列表。
选择合适的瀑布流插件
在 Vue3 生态系统中,有多个瀑布流插件可供选择。经过对比和实际测试,我们最终选择了 vue-waterfall-next
插件。它提供了简单易用的 API,支持动态加载数据和无限滚动,并且具有自定义配置选项,如列数、间距等。
安装和引入插件
首先,我们需要安装 vue-waterfall-next
插件。在项目根目录下运行以下命令:
npm install vue-waterfall-plugin-next
然后,在 Vue 项目中引入插件:
import { LazyImg, Waterfall } from 'vue-waterfall-plugin-next' import 'vue-waterfall-plugin-next/dist/style.css'
实现滚动分页加载
虽然 vue-waterfall-next
插件可以实现瀑布流布局,但它本身并不支持滚动分页加载。为了解决这个问题,我们使用了原生 JavaScript 来实现无限滚动加载。
父组件实现
在父组件中,我们定义了分页相关的变量和方法:
<script> import productCard from '@/components/productCard.vue' import { getAllGoods } from '@/api/modules/good.js' export default { components: { productCard, }, setup() { const page = ref(0) const size = ref(8) const loading = ref(false) const finish = ref(false) const productList = ref([]) // 获取接口数据 const getProduct = () => { loading.value = true const params = { page: page.value, size: size.value, body: { goodsTypeID: className, }, } getAllGoods(params) .then(res => { if (res.code === 20000) { total.value = Number(res.data.totalPages) if (res.data.list.length > 0) { productList.value = [...productList.value, ...res.data.list] } if (page.value == total.value + 1) { finish.value = true loading.value = false } } else { loading.value = false finish.value = true } }) .catch(err => { loading.value = false finish.value = true }) } // 监听滚动事件 const handleScroll = () => { const scrollHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight) const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop const clientHeight = window.innerHeight || Math.min(document.documentElement.clientHeight, document.body.clientHeight) if (clientHeight + scrollTop >= scrollHeight && page.value <= total.value) { page.value++ getProduct() } } onMounted(() => { getProduct() window.addEventListener('scroll', handleScroll) }) onUnmounted(() => { window.removeEventListener('scroll', handleScroll) }) return { productList, loading, finish, } } } </script>
子组件实现
在子组件中,我们使用 vue-waterfall-next
插件来实现瀑布流布局:
<template> <Waterfall :lazyload="false" :breakpoints="breakpoints" :gutter="8" :list="list"> <template #item="{ item, url, index }"> <div class="card_content"> <div class="card_img" :class="{ active: !item.goodsPicture && !item.storePicture }"> <LazyImg class="cover" :url="item.goodsPicture || item.storePicture || item.storeLogo" /> </div> <div class="content"> <div class="store" v-if="item.type === 2">{{ item.storeName }}</div> <div class="title" v-if="item.type === 1">{{ item.storeName }}</div> <div class="title" v-if="item.type === 2">{{ item.goodsName }}</div> <div class="tags"> <div class="tags-item" v-for="(ele, index) in item.tags" :key="index"> {{ ele }} </div> </div> </div> </div> </template> </Waterfall> </template> <script> import { computed, ref } from 'vue' import { LazyImg, Waterfall } from 'vue-waterfall-plugin-next' import 'vue-waterfall-plugin-next/dist/style.css' export default { props: { productList: Array, }, components: { LazyImg, Waterfall, }, setup(props) { const list = computed(() => { return props.productList }) const breakpoints = ref({ 1200: { rowPerView: 4, }, 800: { rowPerView: 3, }, 500: { rowPerView: 2, }, }) return { breakpoints, list, } }, } </script>
优化滚动加载
在测试过程中,我们发现滚动过快时页面会出现抖动现象。为了解决这个问题,我们在监听页面滚动时添加了一个防抖函数:
const debounce = (fn, delay) => { let timeout return function () { clearTimeout(timeout) timeout = setTimeout(() => { fn.apply(this, arguments) }, delay) } } onMounted(() => { getProduct() window.addEventListener('scroll', debounce(handleScroll, 200)) })
总结
在 Vue3 项目中实现滚动分页加载瀑布流列表并不复杂。通过使用 vue-waterfall-next
插件和原生 JavaScript 的结合,我们可以轻松地实现这一功能。希望这篇文章能够帮助你在项目中实现类似的瀑布流效果。