课程名称: CRMEB uniapp电商项目二次开发实战
课程章节: 5-9 商品列表加载更多及已加载完所有功能完善
课程讲师: CRMEB
课程内容:
1、创建商品为空页面显示内容Empty.vue
<template>
<view class="empty">
<view class="empty-container">
<image :src="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 :src="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,显示数据加载完成