点击food展开详情页food.vue的实现
1)新建good文件夹和good.vue,设置样式,并接受一个被选中的food
props: { //接收传入的food
food: {
type: Object
}
}
2)获取food数据,goods.vue中
food是由goods组件传出的,现在goods组件中引入food,并从data中将被选中的food传入food.vue中
<food :food="selectedFood"></food>
其中,selectedFood初始化为空对象,一开始没有food被选择
data{
selectedFood: {} //一开始是空对象,点击food的时候再存入,在li(food)中添加点击事件
}
之后在goos.vue的food列表中添加点击事件,点击food之后,更新selectedFood{}
<li @click="selectFood(food,$event)" v-for="food in item.foods" :key="food.id" class="food-item" border-1px>
<li @click="selectFood(food,$event)" v-for="food in item.foods" :key="food.id" class="food-item" border-1px>
selectFood(food, event){ //@click函数
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
this.selectedFood = food; //更新data中的selectedFood
}
最后,如1),在food.vue中接收food数据
3)在goods.vue中,点击一种food的时候会弹出food.vue中的详情界面,添加this.$refs.food.show();
<li v-for="food in item.foods" :key="food.id" class="food-item" border-1px @click="selectFood(food,$event)">
selectFood(food, event) { //@click函数
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
this.selectedFood = food;
//调用子组件的show()方法展开food组件
this.$refs.food.show();
}
},
在food.vue中添加show()方法
show() { //可以被父组件调用到,方法前加下划线一般是私有方法
this.showFlag = true;
//初始化部分,ratingselect组件是被被不同的商品使用的,所以我们希望在点开不同的商品时,能有一样的初始化状态
this.selectType = ALL;
this.onlyContent = false;
//展示界面时用到BScroll
this.$nextTick(() => {
if (!this.scroll) {
this.scroll = new BScroll(this.$refs.food, {
click: true // 可以被点击
});
} else {
this.scroll.refresh();
}
});
},
4)布局food页面,添加图片,并为图片左上角添加返回按钮
<div class="image-header">
<img :src="food.image" alt="">
<div class="back" @click="hide">
<i class="icon-arrow_lift"></i>
</div>
</div>
hide() {
this.showFlag = false;
},
<div v-show="showFlag" class="food" ref="food"> 实际上改变的是show方法中showFlage的值
5)添加商品名称,月售价格等部分+CSS布局
6) good.vue是定长的,我们希望添加BScroll实现滚动布局,将BScroll绑定在最外层,为其添加ref,让其DOM可以被访问到,BScroll应该在界面呈现时用到,将其添加到show()方法(界面呈现)中
good.vue中
show() { //可以被父组件调用到,方法前加下划线一般是私有方法
this.showFlag = true;
//ratingselect组件是被被不同的商品使用的,所以我们希望在点开不同的商品时,能有一样的初始化状态
this.selectType = ALL;
this.onlyContent = true;
//展示界面时用到BScroll
this.$nextTick(() => {
if (!this.scroll) {
this.scroll = new BScroll(this.$refs.food, {
click: true // 可以被点击
});
} else {
this.scroll.refresh();
}
});
},
food.vue中
selectFood(food, event) { //@click函数
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
this.selectedFood = food;
//调用子组件的show()方法展开food组件
this.$refs.food.show();
}
7)添加加入购物车按钮,点击加入购物车之后,出现cartcontrol加减号按钮
<div class="cartcontrol-wrapper"> <!-- 加减号组件cartcontrol -->
<cartcontrol :food="food"></cartcontrol>
</div>
<transition name="fade">
<div @click.stop.prevent="addFirst" class="buy" v-show="food.count === 0 || !food.count">
加入购物车
</div> <!-- 这两种情况下加入购物车都会显示,否则就会隐藏-->
</transition>
1.当food.count=0或者是不存在food.count(没有在goods.vue界面被点击过的情况)时,才会出现添加购物车字样,否则显示cartcontrol加减号组件
2.点击了加入购物车按钮之后,出发addFirst()事件,即第一次添加事件,这是加入购物车字样转变为加减号组件
addFirst(event) { // 默认的参数是event,点击按钮的时候添加的是第一个商品
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
//第一次的时候el消失,找不到小球发出的其实位置,所以第一次小球动画消失
//解决办法就是将购物车的消失做成一个动画,而不是立马display:none
//添加的时候添加小球动画,派发事件,之后goods.vue就可以监听到cart-add,并传递给shopcart.vue
this.$emit('cart-add', event.target);
Vue.set(this.food, 'count', 1); //初始化this.food.count = 1;
}
3.父组件goods.vue中进行监听
cartAdd(target) {
//拿到traget(DOM对象)之后,将其传入shopcart组件中drop(target){}方法,
//此处用this.$refs调用子组件,访问DOM时用的是ref="menuWrapper"
this.$nextTick(() => { //回调函数异步执行,两个动画效果就不会卡顿了
this.$refs.shopcart.drop(target);
});
},
<div class="cartcontrol-wrapper">
<cartcontrol v-on:cart-add="cartAdd" :food="food"></cartcontrol> <!-- 传入food!!!-->
</div>
CSS:
.cartcontrol-wrapper
position absolute
right 12px
bottom 12px
.buy
position absolute
right 18px
bottom 18px
z-index 10 // 要盖住加减号组件
height 24px
line-height 24px
padding 0 12px
box-sizing border-box
font-size 10px
border-radius 10px
color #ffffff
background rgb(0,160,220)
&.fade-enter-active, &.fade-leave-active
transition all 0.2s
opacity 1
&.fade-enter, &fade-leave-active
opacity 0
8)在goods组件点击加减号cartcontrol的时候,也会引起good详情页的出现,此时在cartcontrol中阻止加减号的冒泡即可,同时对加入购物车的click也设置阻止冒泡
<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart">
<div class="cart-add icon-add_circle" @click.stop.prevent="addCart"></div>
<div @click.stop.prevent="addFirst" class="buy" v-show="food.count === 0 || !food.count">
9)split组件的实现(多次出现的一个分割样式,将其抽象为组件)
<template>
<div class="split"></div>
</template>
<script type="text/ecmascript-6">
export default {};
</script>
<style lang="stylus" rel="stylesheet/stylus">
.split
width 100%
height 16px
border-top: 1px solid rgba(1, 17, 27, 0.1);
border-bottom: 1px solid rgba(1, 17, 27, 0.1);
background: #f3f5f7
</style>
在food.vue引入注册之后就可以使用了