vue通用商品详情页
<template>
<div class="goodsinfo-container">
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div class="ball" v-show="ballFlag"></div>
</transition>
<div class="ball"></div>
<div class="mui-card">
<div class="mui-card-content">
<div class="mui-card-content-inner">
<swiper :swiperList="swiperList" :isfull="true"></swiper>
</div>
</div>
</div>
<div class="mui-card">
<div class="mui-card-header"></div>
<div class="mui-card-content">
<div class="mui-card-content-inner">
<p class="price">
市场价:<del>¥{{ goodsinfo.market_price }}</del> 销售价:<span class="now_price">¥{{ goodsinfo.sell }}</span>
</p>
<p>购买数量:<numbox @getcount="getSelectedCount" :max="goodsinfo.stock_quantity"></numbox></p>
<p>
<mt-button type="primary" size="small">立即购买</mt-button>
<mt-button type="danger" size="small">加入购物车</mt-button>
</p>
</div>
</div>
<div class="mui-card-footer"></div>
</div>
<div class="mui-card">
<div class="mui-card-header">{{ goodsinfo.title }}</div>
<div class="mui-card-content">
<div class="mui-card-content-inner">
<p>商品货号:{{ goodsinfo.goods_no }}</p>
<p>库存情况:{{ goodsinfo.stock_quantity }}</p>
<p>上架时间:{{ goodsinfo.add_time | dataFormat }}</p>
</div>
</div>
<div class="mui-card-footer">
<mt-button type="primary" size="large" plain>图文介绍</mt-button>
<mt-button type="danger" size="large" plain>商品评论</mt-button>
</div>
</div>
</div>
</template>
<script>
import swiper from '../subcomponents/swiper.vue'
import numbox from '../subcomponents/numbox.vue'
export default {
data(){
return {
id: this.$route.params.id,
lunbotu: [],
goodsinfo: {},
ballFlag: false,
selectedCount: 1
}
},
created(){
this.getLunbotu()
},
methods:{
getLunbotu(){
this.$http.get("数据接口" + this.id).then(result => {
if (result.body.status === 0) {
result.body.message.forEach(item => {
item.img = item.src
})
this.lunbotu = result.body.message
}
})
},
getGoodsInfo(){
this.$http.get('数据接口' + this.id).then(result => {
if (result.body.status === 0) {
this.goodsinfo = result.body.message[0];
}
})
},
goDesc(id) {
this.$router.push({ name: "goodsdesc", params: { id } });
},
goComment(id) {
this.$router.push({ name: "goodscomment", params: { id } });
},
addToshopCar(){
this.ballFlag = this.ballFlag
},
beforeEnter(el){
el.style.transform = "translate(0, 0)"
},
enter(el, done){
el.offsetWidth;
const ballPosition = this.$refs.ball.getBoundingClientRect();
const badgePosition = document.getElementById('badge').getBoundingClientRect();
const xDist = badgePosition.left - ballPosition.left;
const yDist = badgePosition.top - ballPosition.top;
el.style.transform = `translate($(xDist)px, $(yDist)px)`;
el.style.transition = "all 1s cubic-bezier(.4,-0.3,1,.68)";
done();
},
afterEnter(el){
this.ballFlag = !this.ballFlag
},
getSelectedCount(count){
this.selectedCount = count;
}
},
components: {
swiper,
numbox
}
}
</script>
<style lang="scss" scoped>
.goodsinfo-container {
background-color: #eee;
overflow: hidden;
.now_price {
color: red;
font-size: 16px;
font-weight: bold;
}
.mui-card-footer{
display: block;
button{
margin: 10px 0;
}
}
.ball{
width: 90px;
height: 90px;
border-radius: 50%;
background-color: red;
z-index: 99;
top: 390px;
left: 146px;
transform: translate(88px, 230px)
}
}
</style>
数字盒子
<template>
<div class="mui-numbox" data-numbox-min='1' data-numbox-max='max'>
<button class="mui-btn mui-btn-numbox-minus" type="button">-</button>
<input id="test" class="mui-input-numbox" type="number" value="1" @change="countChanged" ref="numbox" />
<button class="mui-btn mui-btn-numbox-plus" type="button">+</button>
</div>
</template>
<script>
import mui from '../../lib/mui/js/mui.min.js'
export default {
mounted(){
mui(".mui-numbox").numbox();
},
methods:{
countChanged(){
this.$emit("getcount", parseInt(this.$refs.numbox.value));
}
},
props: ["max"],
watch:{
'max':function(newVal, oldVal){
mui(Selector).numbox().setOption("max", newVal)
}
}
}
</script>
<style lang="scss" scoped>
</style>
轮播图组件
<template>
<div>
<mt-swipe :auto="4000">
<mt-swipe-item v-for="item in swiperList" :key="item.url">
<img src="item.img" alt="" :class="{'full': isfull}">
</mt-swipe-item>
</mt-swipe>
</div>
</template>
<script>
export default {
props: ["swiperList", "isfull"]
}
</script>
<style lang="scss" scoped>
.mint-swipe {
height: 200px;
.mint-swipe-item {
&:nth-child(1){
}
&:nth-child(2){
}
&:nth-child(3){
}
img{
height: 100%;
}
}
}
.full{
width: 100%;
}
</style>
关键问题
- 轮播图的自适应问题:
<img src="item.img" alt="" :class="{'full': isfull}">
.full{
width: 100%;
}
- 小球动画
半场动画+ref组件操作+@change事件绑定+滚动条和分辨率适配算法
<input id="test" class="mui-input-numbox" type="number" value="1" @change="countChanged" ref="numbox"
beforeEnter(el){
el.style.transform = "translate(0, 0)"
},
enter(el, done){
el.offsetWidth;
const ballPosition = this.$refs.ball.getBoundingClientRect();
const badgePosition = document.getElementById('badge').getBoundingClientRect();
const xDist = badgePosition.left - ballPosition.left;
const yDist = badgePosition.top - ballPosition.top;
el.style.transform = `translate($(xDist)px, $(yDist)px)`;
el.style.transition = "all 1s cubic-bezier(.4,-0.3,1,.68)";
done();
},
afterEnter(el){
this.ballFlag = !this.ballFlag
},
- $emit 子组件向父组件传值
<p>购买数量:<numbox @getcount="getSelectedCount"
methods:{
countChanged(){
this.$emit("getcount", parseInt(this.$refs.numbox.value));
}
},
- watch监听max
watch:{
'max':function(newVal, oldVal){
mui(Selector).numbox().setOption("max", newVal)
}
}