创建cartcontrol组件,组件关联到food的相关属性,价格,数量等,所以组件要props父组件goods传过来的food数据
export default {
//父组件传过来的,接收一个props属性来计算商品的个数,food.count,去goods组件中引入cartcontrol
props: {
food: {
type: Object
}
}
布局:分三层,减少,数量num,增加,food.count>0时才会出现减少和数量的div
<div class="cartcontrol">
<transition name="fade"> <!-- 外层渐变,减号图标-->
<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart">
<transition name="inner"> <!-- 内层滚动,滚动时包含字体,字体在inner中-->
<span class="inner icon-remove_circle_outline"></span>
</transition>
</div>
</transition>
<div class="cart-count" v-show="food.count > 0">{{food.count}}</div>
<div class="cart-add icon-add_circle" @click.stop.prevent="addCart"></div> <!-- 加号图标 -->
</div>
在goods中引入并注册组件,然后在模板里应用组件,每个food的下边都有一个加减号组件,组件应包含在content中,即在价格的右边,并将food传入
<div class="price">
<span class="now">¥{{food.price}}</span><span class="old" v-show="food.oldPrice">¥{{food.oldPrice}}</span>
</div>
<div class="cartcontrol-wrapper">
<cartcontrol v-on:cart-add="cartAdd" :food="food"></cartcontrol> <!-- 传入food!!!-->
</div>
并为cartcontrol-wrapper添加样式,将其固定在右侧
.cartcontrol-wrapper
position absolute
right 0
bottom 24px
在加减号组件中created中logs一下food,看是否能正确拿到food的值
created() {
// console.log(this.food); //忘记加this
}
接下来给cartContronl写样式,简单的样式,没有添加动画
之后在,加号部分添加一个点击事件,点击之后,改变food.count的值
<div class="cart-add icon-add_circle" @click.stop.prevent="addCart"></div> <!-- 加号图标 -->
因为goods组件中用了betterScroll组件,所以我们在点击goods组件图层上的加减号组件时,不要忘了在初始化滚动组件的时候为其添加click:true允许点击
在goods中初始化时:
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
click: true,
probeType: 3 //BScroll滚动时,能实时告诉我们滚动的位置,类似探针的效果
});
addCart(event) {
//解决PC端双点击的问题
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
//console.log('click');//点击不生效,不要忘了在foodScroll中添加click: true
if (!this.food.count) {
//food.count是原json中不存在的属性,不能直接添加
//this.food.count = 1;
Vue.set(this.food, 'count', 1);//给this.food增加一个count属性,并初始化为1
} else {
this.food.count++;
}
}
我们发现我们添加的约束条件当food.count>0时,并没有出现数字和减号,这是因为count是food中不存在的属性,propty检测不到属性的变化, 我们要为其添加count这个属性
import Vue from 'vue';
Vue.set(this.food, 'count', 1);//给this.food增加一个count属性,并初始化为1
给count添加css属性之后,count即可出现,而且我们可以利用padding增加按钮的点击区域
.cart-count
display inline-block
vertical-align top
width 12px
padding-top 8px
line-height 24px
text-align center
font-size 16px
color rgb(147,153,159)
为减号添加一个点击事件
<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart">
decreaseCart(event) {
//解决PC端双点击的问题
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
if (this.food.count) {
this.food.count--;
}
}
最后,为加减号添加滚动的动画,点击加号的时候减号的按钮时从右到左滚动过来的,这样就有两个动画平移加滚动,还需要一个透明度从0到1的一个渐变过程,所以减组件需要两个层级,外层负责平移,内层负责滚动,表示字体的层应该放到内层
<transition name="fade"> <!-- 外层渐变,减号图标-->
<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart">
<transition name="inner"> <!-- 内层滚动,滚动时包含字体,字体在inner中-->
<span class="inner icon-remove_circle_outline"></span>
</transition>
</div>
</transition>
.cartcontrol
font-size 0 // 消除incline-block中的空隙
.cart-decrease, .cart-add
display inline-block // 横向排列
padding 6px // 图标较小,增加它的点击区域
&.fade-enter-active, &.fade-leave-active //进入动画的状态/离开动画时生效
transition: all 0.4s linear
opacity 1
transform translate3d(0, 0, 0)
&.fade-enter, &.fade-leave-active //动画的开始状态,动画一开始透明度要设为0/离开动画的结束状态
opacity: 0
transform translate3d(24px, 0, 0)
.inner
display inline-block //有宽高
line-height 24px
font-size 24px
vertical-align top
color rgb(0, 160, 220, 0.2)
&.inner-enter-active, &.inner-leave-active
transition: all 0.4s linear
opacity 1
transform: rotate(0)
&.inner-enter, &.inner-leave-active
opacity: 0
transform rotate(180deg)
我们通过加减号组件修改了food的count属性,要将count的变化通知其父组件goods,然后goods通过计算得出selectFoods的变化,通知到购物车组件
首先在goods.vue中编写selectFoods,selectFoods组件要遍历所有的goods(计算属性),selectFood是一个计算属性,它观测的就是就是goods对象,goods发生变化他会重新计算进行更新
//用data绑定goods,以便后续添加到DOM中
data() {
return {
goods: [],
listHeight: [], //存储区块的高度
};
}
selectFoods() { //遍历foods,看看选中了哪些商品
let foods = [];
this.goods.forEach((good) => { //先取到每一个分类
good.foods.forEach((food) => { //后取到每一个分类下的不同food
if (food.count) {
foods.push(food); //两层遍历,取到所有被选中的foods
}
});
});
return foods; //将结果传回到shopcart
}
}
再将selectFoods的结果传递到cartcontrol(购物车)组件中,这样,在点击加减号时改变了food的count属性,count的变化传回到父组件,然后在父组件中遍历goods下的foods,就取到了所有被选中的foods,将其返回值传递到shopCart中,就完成了加减号与购物车的同步联动
<shopcart ref="shopcart" :select-foods="selectFoods" :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"></shopcart>
之后,为加减号添加动画小球的特效