一、商品数据的请求
要展示商品数据,我们最先要做的就是要先把数据请求下来
因为我们的TabControl中有三个数据,所以我们请求数据的时候也分为三大类
保存商品的数据结构:
goods:{流行[]/新款[]/精选[]}它对应的每一个都是数组,每一个数组可能保存30条,60条,90条等,它会有上拉加载更多,到时候保存的数据量是不一样的。还会出现,我流行的数据已经加载到第8页,新款加载到第5页,而精选也才加载到第三页的情况,这时,我们就需要设计数据结构了
goods:{
'pop':{page: 1,list:[]},//默认page是第一页,流行对应的pop里的数据都存放在list里面,page是用来记录我当前加载数据,加载到第几页
'news':{page: 1,list:[]},
'sell':{page: 1,list:[]}
在data中
goods: {
'pop':{page:0,list:[]},
'new':{page:0,list:[]},
'sell':{page:0,list:[]},
},
先请求数据:在home.js中
export function getHomeGoods(type, page) {
return request({
url: "/home/data",
params: {
type,
page,
},
});
}
导入到Home.vue中
import {getHomeMultidata,getHomeGoods} from '@/network/home';
什么时候发送请求呢?我们可以在我们的组件创建之后就立即发送请求,所以我们在created中
created(){
//请求商品的多个数据
this.getHomeGoods('pop')
this.getHomeGoods('new')
this.getHomeGoods('sell')
}
但是此时created()里面放的东西太多了,我们此时再抽取一层,存放主要逻辑,将这一抽取的内容放入到methods中,此时的代码就变成了
created() {
//组件创建完以后,赶紧发送网络请求,请求多个数据
// create里面的this就是我们当前的组件对象
this.getHomeMultidata()
//网络请求相关(请求商品数据)
this.getHomeGoods('pop')
this.getHomeGoods('new')
this.getHomeGoods('sell')
},
methods: {
getHomeMultidata() {
getHomeMultidata().then(res => {
// console.log(res);
this.banners = res.data.banner.list;
this.recommends = res.data.recommend.list;
})
},
getHomeGoods(type) {
const page = this.goods[type].page + 1
getHomeGoods('pop', page).then(res => {
this.goods[type].list.push(...res.data.list)
this.goods[type].page += 1
})
}
}
我们首先都将第一页请求下来,后面的就用下拉加载更多来做。其中 getHomeGoods(type)里面的这个type就是tabControl里面的某个参数。
其中
const page = this.goods[type].page + 1
这一句表示的是,在我原来page的基础之上+1。假如说我请求的是’pop’里面的数据,那type就是pop,取到了’pop’:{page:0,list:[]}这个对象拿到它的page然后+1。最开始为0,后面+1变为了1,等我下一次取得时候page就为1,再+1就变成了2。再将我们最新的page放入到下面 getHomeGoods(‘pop’, page)这个里面,此时这个里面的res表示的是pop的前30条数据,page:1,此时拿到这个变量是一个局部变量,函数结束以后是要被销毁的。所以我们要将这个数据放入到对应的list中保存
this.goods[type].list.push(...res.data.list)
此时pop中的数据多了一组,page+1
this.goods[type].page += 1
二、商品数据的展示
我们在content文件夹中新建goods文件夹,里面存放GoodList.vue和GoodListItem.vue
在GoodList.vue我们
<template>
<div class="goods">
<goods-list-item v-for="item in goods" :goods-item="item">
</goods-list-item>
</div>
</template>
<script>
import GoodsListItem from '@/components/content/goods/GoodsListItem';
export default {
name: 'GoodsList',
components:{
GoodsListItem
},
props:{
goods: {
type:Array,
default() {
return [];
}
}
}
};
</script>
<style scoped>
.goods {
display: flex;
/*flex-wrap则可以将容器设置为是否可换行,nowrap即不换行,其子元素的中宽度大于容器的宽度时,子元素的宽度会被挤压变小*/
/* wrap 即换行,其子元素的宽度不会被挤压变小*/
flex-wrap: wrap;
/*均等分*/
justify-content: space-around;
padding: 2px;
}
</style>
我们先要接收从Home.vue中传入的值:将GoodList.vue在Home.vue中导入,注册,引用
<goods-list :goods="goods['pop'].list"></goods-list>
传出goods数据,在GoodList.vue中接收
props:{
goods: {
type:Array,
default() {
return [];
}
}
}
再将每个小的item传入到GoodListItem.vue组件中
<goods-list-item v-for="item in goods" :goods-item="item">
</goods-list-item>
在GoodListItem.vue中
<template>
<div class="goods-item" @click="itemClick">
<img :src="showImage" :key="showImage" alt="" @load="imageLoad" >
<div class="goods-info">
<p>{{goodsItem.title}}</p>
<span class="price">{{goodsItem.price}}</span>
<span class="collect">{{goodsItem.cfav}}</span>
</div>
</div>
</template>
<script>
export default {
name: 'GoodsListItem',
props:{
goodsItem:{
type:Object,
default() {
return [];
}
}
},
};
</script>
<style scoped>
.goods-item {
padding-bottom: 40px;
width: 48%;
position: relative;
}
.goods-item img {
width: 100%;
border-radius: 5px;
}
.goods-info {
font-size: 12px;
position: absolute;
bottom: 5px;
left: 0;
right: 0;
overflow: hidden;
text-align: center;
}
.goods-info p {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 3px;
}
.goods-info .price {
color: var(--color-high-text);
margin-right: 20px;
}
.goods-info .collect::before {
content: '';
position: absolute;
left: -15px;
top: -1px;
width: 14px;
height: 14px;
background: url("~assets/img/common/collect.svg") 0 0/14px 14px;
}
</style>
接收由GoodList.vue中传入的item中的数据,其中item中的数据具体如下:
我们希望展示的东西上面代码已经写过,具体样式也如下面的style中所写。
综上,效果如下: