课程名称: CRMEB uniapp电商项目二次开发实战
课程章节: 5-9 商品列表加载更多及已加载完所有功能完善
课程讲师: CRMEB
课程内容:
1、创建商品为空页面显示内容Empty.vue
<template> <view class="empty"> <view class="empty-container"> <image :class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="emptyImg"></image> </view> </view> </template> <script> import emptyImg from '@/static/images/noShopper.png' export default { data () { return { emptyImg } } } </script> <style lang="scss" scoped> .empty { &-container { image { display: block; width: 414rpx; height: 336rpx; margin: 30rpx auto; } } } </style>
2、在商品列表中导入数据为空后的引用
<template> <Empty v-if="noneProduct"></Empty> </template> <script>' import Empty from './Empty' export default { components: { Empty, NoMore } } </script>
3、在最外新建components目录创建公共的数据加载完成的组件NoMore.vue
<template> <view class="no-more"> <view class="no-more-container"> <text>已加载完所有数据~</text> </view> </view> </template> <script> </script> <style lang="scss" scoped> .no-more { &-container { padding: 60rpx 30rpx 20rpx; text-align: center; font-size: 24rpx; } } </style>
4、在项目列表中调用使用加载更多的项目
<template> <view class="product-list"> <view class="product-list-container" :class="[showMode, noneProduct ? 'none' : '']"> <view class="list" :class="[showMode]" v-if="!noneProduct"> <navigator v-for="goods in list" :key="goods.id" :url="`/pages/goods_detail/goods_detail?gid=${goods.id}`" hover-class="none" class="item"> <image :class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="goods.image"></image> <view class="info"> <view class="name">{{ goods.store_name }}</view> <view class="price">¥{{ goods.price }}</view> <view class="sales">已售{{ goods.sales }}件</view> </view> </navigator> </view> <Empty v-if="noneProduct"></Empty> <NoMore v-show="noMore"></NoMore> </view> </view> </template> <script> import NoMore from '@/components/NoMore' import Empty from './Empty' export default { components: { Empty, NoMore }, props: { list: { type: Array, default: () => [] }, showMode: { type: String, default: '' } }, data () { return { } }, computed: { noneProduct () { return this.list.length === 0 }, noMore () { return this.$parent.noMore } }, methods: { } } </script> <style lang="scss" scoped> .product-list { &-container { min-height: calc(100vh - 86rpx - 86rpx); padding: 0 30rpx 42rpx; margin: 172rpx 0 0 0; box-sizing: border-box; &.pailie { background-color: #f5f5f5; } &.tupianpailie { &.none { background-color: #f5f5f5; } } } .list { &.pailie { display: flex; flex-wrap: wrap; justify-content: space-between; .item { width: 334rpx; border: 1rpx solid #eee; border-radius: 20rpx; margin-top: 20rpx; background-color: #fff; image { width: 100%; height: 334rpx; } .info { padding: 20rpx 16rpx 26rpx 16rpx; .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 30rpx; color: #222; } .price { font-size: 34rpx; color: #fc4141; } .sales { font-size: 22rpx; color: #aaa; } } } } &.tupianpailie { .item { display: flex; padding: 30rpx 0; border-bottom: 1rpx solid #eee; border-radius: 20rpx; margin-top: 20rpx; image { width: 180rpx; min-width: 180rpx; height: 180rpx; } .info { padding: 20rpx 16rpx 26rpx 16rpx; .name { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font-size: 30rpx; color: #222; } .price { font-size: 34rpx; color: #fc4141; } .sales { font-size: 22rpx; color: #aaa; } } } } } } </style>
5、判断数据加载完成,筛选数据为空
<template> <view class="goods-list"> <view class="goods-list-container"> <Search @search="onSearch" @switch-mode="onSwitchShowMode"></Search> <Sort @sort="onSort" ref="sort"></Sort> <ProductList :list="goodsList" :showMode="showMode"></ProductList> </view> </view> </template> <script> import { productList as productListApi } from '@/api/goods' import Search from './components/Search' import Sort from './components/Sort' import ProductList from './components/ProductList' export default { components: { Search, Sort, ProductList }, data() { return { params: { // 一级分类id cid: 0, // 二级分类id sid: 0, // 搜索关键词 keyword: '', // 价格排序 priceOrder: '', // 按销量排序 salesOrder: '', // 是否新品 news: '', page: 1, limit: 20, }, goodsList: [], showMode: '', noMore: false } }, onLoad (options) { this.params.sid = options.sid this.$refs.sort.menuList[0].text = options.sname this.getProductList() }, onReachBottom () { this.getProductList() }, methods: { onSearch (keywords) { this.params.keyword = keywords this.params.page = 1 this.noMore = false this.getProductList() }, onSwitchShowMode (modeName) { this.showMode = modeName }, onSort (sortParams) { this.params = {...this.params, ...sortParams} this.params.page = 1 this.noMore = false this.getProductList() }, async getProductList () { if (this.noMore) { return false } const { status, data, msg } = await productListApi(this.params) if (status === this.API_STATUS_CODE.SUCCESS) { if (this.params.page > 1) { this.goodsList = [...this.goodsList, ...data] if (data.length === 0) { this.noMore = true } } else { this.goodsList = data } if (data.length) { this.params.page++ } } else { uni.showToast({ icon: 'none', title: msg, duration: 3000 }) } } } } </script> <style lang="scss" scoped> </style>
课程收获:
这节课主要学习到了在父组件中访问子组件,首先在子组件中定义ref=“任意名称”,然后通过在父组件中this.KaTeX parse error: Expected 'EOF', got '来' at position 29: …uList[0].text 来̲访问子组件的数据,子组件访问父…parent.noMore,再有学习到了uniapp中页面触底的生命周期函数onReachBottom(页面滚动到底部的事件(不是scroll-view滚到底),常用于下拉下一页数据。具体见下方注意事项),加载更多数据数据为空后通过定义一个noMore值,进行判断,然后再通过加载请求数据,加入数据为空,就设置为true,显示数据加载完成