Files
lgp-wx-plus/mixins/productWaterfall.js
2026-08-20 19:15:41 +08:00

105 lines
3.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 商品瀑布流通用 mixin
*
* product.vue / search.vue 的瀑布流高度同构:data 字段、按列数拆列 computed、
* 触底加载更多、下拉刷新这些样板代码两边一模一样。这里抽公共,避免改一处忘改另一处。
*
* 约定(引入本 mixin 的页面必须遵守):
* - 页面自己实现 getProductList():负责调接口、按 this.page 把结果赋值/追加到 this.products、
* 维护 this.noMoreData 与 this.loading / this.loadingMore。
* - getProductList 应返回 Promise(供 refreshProductList 关闭下拉动画)。
* - 页面的 onReachBottom / onPullDownRefresh 不用再写,mixin 已接管。
*
* 故意只抽 data + computed + 两个生命周期,不把 getProductList 收进来,
* 因为两个页面的请求参数不同(product 带 category_id,search 只带 title),硬塞进来反而更乱。
*/
export default {
data() {
return {
// 当前页码,从 1 开始
page: 1,
// 每页条数,与后端约定 10
pageSize: 10,
// 商品列表(扁平数组),computed 按 pcGoodsCols 拆成 N 列
products: [],
// 首屏 loading(控制骨架屏显隐)
loading: false,
// 触底加载更多 loading
loadingMore: false,
// 是否没有更多数据
noMoreData: false,
// 后端总页数(部分接口会带 last_page)
totalPages: 1,
}
},
computed: {
/**
* 按当前窗口列数把商品轮流分进各列,宽屏一行更多而不是两列撑满。
* 依赖 theme mixin 的 pcGoodsCols;两个列表页都混了 theme。
*/
productColumns() {
const n = Math.max(2, Number(this.pcGoodsCols) || 2)
const cols = Array.from({ length: n }, () => [])
this.products.forEach((item, index) => {
cols[index % n].push(item)
})
return cols
},
},
onPullDownRefresh() {
this.refreshProductList()
},
onReachBottom() {
this.loadMoreProducts()
},
methods: {
/**
* 下拉刷新:回到第一页重新拉,结束后关闭下拉动画 + toast
* 依赖页面 getProductList 返回 Promise
*/
refreshProductList() {
this.page = 1
this.products = []
this.noMoreData = false
const p = this.getProductList()
Promise.resolve(p)
.then(() => {
uni.stopPullDownRefresh()
uni.showToast({
title: '刷新成功',
icon: 'success',
duration: 1500,
})
})
.catch(() => {
uni.stopPullDownRefresh()
uni.showToast({
title: '刷新失败',
icon: 'none',
duration: 1500,
})
})
},
/**
* 触底加载更多:加锁 + 页码 +1 后交页面 getProductList 处理
* 失败时回退页码,避免下次再触底跳页
*/
loadMoreProducts() {
if (this.loadingMore || this.noMoreData) return
this.page++
this.loadingMore = true
Promise.resolve(this.getProductList())
.catch(() => {
this.page--
uni.showToast({
title: '加载失败',
icon: 'none',
})
})
.finally(() => {
this.loadingMore = false
})
},
},
}