您当前的位置: 首页 > 学无止境 > JS经典实例 网站首页JS经典实例
vue项目第四天-商品列表、购物车(商品详情及图文介绍)
发布时间:2020-05-09 19:53:35编辑:雪饮阅读()
商品详情页没有多少出彩的地方,主要是封装了轮播、图文介绍所涉及到的组件跳转及beforeRouteEnter钩子以及合并请求
轮播封装则有
轮播组件封装为Swipe.vue
<template>
<mt-swipe :auto="4000">
<!-- v-for组件的时候需要给key,避免vue计算key,来提升性能 -->
<!-- key就是位置的标识 -->
<mt-swipe-item v-for="(item,index) in imgs||myimgs" :key="index" >
<img :src="item.img||item.src" alt="">
</mt-swipe-item>
</mt-swipe>
</template>
<script>
export default {
name:'my-swipe',
props:['url','imgs'],
data(){
return {
// myimgs:this.imgs
// myimgs的修改不会影响外部的this.imgs的重新渲染
// 子接收父的属性再去做显示,也不能显示成功,内部执行时机问题
myimgs:[]
// 总结: 暂且不把不子属性混为一谈,可能造成不显示或更新失败的问题
}
},
created() {
// 父传递给子的组件,子在接收成为自己的属性后,发生改变的话,不会触发视图更新
console.log('====',this.imgs);
// 兼容传对象的方式
if(this.url) {
this.$axios.get(this.url)
.then(res=>{
this.myimgs = res.data.message;
})
.catch(err=>console.log(err));
}
}
}
</script>
<style scoped>
.mint-swipe {
width: 100%;
height:200px;
}
.mint-swipe img {
width: 100%;
}
</style>
然后src/main.js中同样导入下
则home组件变更下之前的独立的轮播该为调用该公共路边组件
<div class="hello">
<div class="outer-swiper">
<div class="swiper">
<my-swipe :imgs="imgs"/>
</div>
</div>
则home组件的created也要改动下
created() {
this.$axios.get(`/api/getthumimages/0`).then(res=>{
console.log("then res",res);
this.imgs=res.data.message;
}).catch(res=>{
console.log("catch res",res);
});
}
商品详情GoodsDetail.vue
<template>
<div>
<nav-bar title="商品详情"/>
<div class="outer-swiper">
<div class="swiper">
<my-swipe :imgs="imgs"/>
</div>
</div>
<div class="product-desc">
<ul>
<li><span class="product-desc-span">
{{info.title}}
</span></li>
<li class="price-li">市场价:
<s>¥{{info.market_price}}</s> 销售价:<span>¥{{info.sell_price}}</span></li>
<li class="number-li">购买数量:<span>-</span><span>1</span><span>+</span></li>
<li>
<mt-button type="primary">立即购买</mt-button>
<mt-button type="danger">加入购物车</mt-button>
</li>
</ul>
</div>
<div class="ball"></div>
<div class="product-props">
<ul>
<li>商品参数</li>
<li>商品货号:{{info.goods_no}}</li>
<li>库存情况:{{info.stock_quantity}}件</li>
<li>上架时间:{{info.add_time | convertTime('YYYY-MM-DD')}}</li>
</ul>
</div>
<div class="product-info">
<ul>
<li>
<mt-button type="primary" size="large" plain @click="goGoodsInfo">图文介绍</mt-button>
</li>
<li>
<mt-button type="danger" size="large" plain>商品评论</mt-button>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
goodsId:this.$route.query.id,
info:{}, // 商品信息
imgs:[], // 轮播图
}
},
methods: {
goGoodsInfo() {
// 直接进入到新闻详情
this.$router.push({
name:'NewsDetail',
params:{
id:this.$route.query.id
}
});
}
},
created() {
// 商品轮播图 getthumimages/:imgid
// 商品信息 goods/getinfo/:goodsid
// 请求一个失败了,就算做失败
let imgReq = this.$axios.get(`/api/getthumimages/${this.goodsId}?type=1`);
let infoReq = this.$axios.get(`/api/goods/getinfo/${this.goodsId}`);
// 合并请求 $axios.all([]).then(传播响应).catch()
this.$axios.all([imgReq,infoReq])
.then(
this.$axios.spread(
(imgRes,infoRes)=>{
this.imgs = imgRes.data.message;
this.info = infoRes.data.message.data[0];
})
)
.catch(console.log)
}
}
</script>
<style scoped>
.ball-enter-active {
animation: bounce-in 1s;
}
@keyframes bounce-in {
0% {
transform: translate3d(0, 0, 0);
}
50% {
transform: translate3d(140px, -50px, 0);
}
75% {
transform: translate3d(160px, 0px, 0);
}
100% {
transform: translate3d(140px, 300px, 0);
}
}
.swiper {
border: 1px solid rgba(0, 0, 0, 0.2);
margin: 8px;
width: 95%;
border-radius: 15px;
overflow: hidden;
}
.outer-swiper,
.product-desc,
.product-props,
.product-info {
border-radius: 5px;
border: 1px solid rgba(0, 0, 0, 0.2);
margin: 3px;
}
.outer-swiper{
margin-top:80px;
}
/*请ulpadding*/
.outer-swiper ul,
.product-desc ul,
.product-props ul,
.product-info ul {
padding: 0;
}
.product-desc ul li,
.product-props ul li,
.product-info ul li {
list-style: none;
font-size: 15px;
color: rgba(0, 0, 0, 0.5);
margin-top: 8px;
}
.product-desc ul >:nth-child(1) span {
color: blue;
font-size: 22px;
font-weight: bold;
}
.product-desc ul >:nth-child(1) {
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
}
.product-desc ul,
.product-info ul,
.product-props ul {
padding-left: 10px;
}
.price-li span {
color: red;
font-size: 25px;
}
.price-li s {
margin-right: 16px;
}
/*加减*/
.number-li span {
display: inline-block;
border: 2px solid rgba(0, 0, 0, 0.1);
width: 25px;
}
/*商品参数*/
.product-props ul >:nth-child(1) {
text-align: left;
}
.product-props ul:not(:nth-child(1)) {
margin-left: 40px;
}
.product-info ul {
margin-bottom: 70px;
padding: 0 5;
}
.number-li span {
text-align: center;
}
.number-li >:nth-child(2) {
width: 40px;
}
.ball {
border-radius: 50%;
width: 24px;
height: 24px;
position: absolute;
top: 440px;
left: 120px;
display: inline-block;
z-index: 9999;
}
</style>
为了利用之前的新闻详情页面做商品图文介绍,所以该组件也做下兼容
<style scoped>
.tmpl{
margin-top:80px;
margin-bottom: 80px;
}
.news-title p {
color: #0a87f8;
font-size: 20px;
font-weight: bold;
}
.news-title span {
margin-right: 30px;
}
.news-title {
margin-top: 5px;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}
/*主体文章的左右距离*/
.news-content {
overflow: hidden;
display: flex;
}
</style>
<style>
.news-content p img{
width: 100% !important;
}
</style>
<template>
<div class="tmpl">
<nav-bar :title="title" />
<div class="news-title">
<p>{{newsInfo.title}}</p>
<div>
<span>{{newsInfo.click}}次点击</span>
<span>分类:{{newsInfo.category}}</span>
<span>添加时间:{{newsInfo.add_time | convertTime('YYYY-MM-DD')}}</span>
</div>
</div>
<div class="news-content" v-html="newsInfo.content"></div>
</div>
</template>
<script>
export default {
data() {
return {
newsInfo:{}, // 新闻详情数据
title:''
}
},
created() {
// console.log(this.$route.params)
// 1: 获取路由参数
let { id } = this.$route.params;
// 2: 拼接后台url发起请求
let url = '/api/getnew/' + id;
this.$axios.get(url)
.then(res=>{
// 3: 响应的数据渲染到页面上,通过一个详情对象
this.newsInfo = res.data.message[0];
})
.catch(err=> console.log(err));
},
beforeRouteEnter (to, from, next) {
let title = '详情';
let type=1;
console.log("from",from);
// 1: 判断from是新闻列表,还是商品详情
if (from.name === 'NewsList') {
title = '新闻详情';
} else if (from.name === 'GoodsDetail') {
title = '商品图文信息';
type=2;
}
// 这里没有this,因为组件还没有被实例化
next(vm => {
// 通过 `vm` 访问组件实例 就是这里未来的this
vm.title = title;
if(type==2){
let url=`/api/goods/getinfo/${from.query.id}`;
vm.$axios.get(url)
.then(res=>{
// 3: 响应的数据渲染到页面上,通过一个详情对象
vm.newsInfo = res.data.message.data[0];
})
.catch(err=> console.log(err));
}
});
}
}
</script>
关键字词:vue,beforeRouteEnter
上一篇:vue项目第四天商品列表、购物车
下一篇:vue项目第五天