实现购物车中的对商品的数量选择操作,如图1所示,当一开始的时候,界面最右侧只有一个“+”按钮;当点击右侧任意一个“+”按钮的时候,点击的食品的相应地方会出现“-”按钮,并且出现添加的数量,如图2所示;当在点击其他食品的“+”按钮的时候,也会出现点击的食品的相应地方会出现“-”按钮,并且出现添加的数量,同时底部购物车相应的地方也会做出变化,如 图3所示。
图1
图2
图3
下面我们就详细的讲解上述联动的效果是如何实现的。
将右侧的“+”和“-”以及两者之间的数字抽成一个组件,叫做cartControl.vue
1、cartControl.vue的<template>的内容如下,这里用到vue中的内置组件<transition>实现过渡效果
<template>
<div class="cartControl">
<!--当food.count为undefined的时候‘-’有不显示-->
<transition name="move">
<!--decreaseCart()函数在methods中定义,当点击“-”按钮的时候,food.count减一-->
<div class="cartDecrease" v-show="food.count>0" @click="decreaseCart">
<span class="inner icon-remove_circle_outline"></span>
</div>
</transition>
<div class="cartCount" v-show="food.count>0">{{food.count}}</div>
<!--addCart()在methods中定义,点击‘+’,则触发food.count加1-->
<div class="cartAdd icon-add_circle" @click="addCart"></div>
</div>
</template>
2、cartControl.vue的<script>内容 如下,在这里的数据都是基于food对象,即每一种食品
<script>
//这里用到vue的一些方法
import Vue from 'vue';
export default {
props:{
//购物车按钮的控件是和父级元素的每一商品相关联的
food:{
type:Object
}
},
methods:{
//点击food右边的“+”
addCart(event){
if( !event._constructed ){
//不是自己开发的函数,则返回,避免在pc端触发两次
return
}
if( !this.food.count ){
// 如果this.foo.count的值为undefined,表示food对象中还没有count这个属性
// this.food.count = 1;
// set(对象,属性,属性值),让手动添加的属性,被浏览器识别监听
Vue.set(this.food,'count',1);
}else{
this.food.count++;
}
console.log(this.food.count);
},
decreaseCart(event){
if( !event._constructed ){
return;
}
if(this.food.count){
this.food.count--;
}
}
}
}
</script>
这里有用到从父组件传递过来的数据food,所以要在goods.vue中引入并使用cart-control组件,在里面绑定属性food,下图是goods.vue 文件中的修改
在<script>中引入该组件并在components中注册该组件
在<template>中引入该组件
<cart-control :food="food"></cart-control>
3、cartControl.vue中的<style>里面的内容
<style lang="stylus">
.cartControl
font-size:0
.cartDecrease,.cartCount,.cartAdd
display:inline-block
.cartDecrease
padding:6px
opacity: 1
transform: translate3d(0, 0, 0)
.inner
display: inline-block
line-height:24px
font-size:24px
color:rgb(0,160,220)
transition: all 0.4s linear
transform: rotate(0)
&.move-enter-active,&.move-leave-active
transition: all 0.4s linear
&.move-enter, &.move-leave
opacity: 0
transform: translate3d(24px, 0, 0)
.inner
transform: rotate(180deg)
.cartCount
vertical-align: top
width:12px
padding-top:6px
line-height:24px
text-align: center
font-size:10px
color:rgb(147,153,159)
.cartAdd
padding:6px
line-height:24px
font-size:24px
color:rgb(0,160,220)
</style>
由于在子组件cartControl中有将父组件传递过来的food对象添加属性count,当count在cartControl.vue中变化的时候,会自动反映到父组件goods.vue中的food
由于,要将变化的food的属性要反映到shopCart.vue 中,所以需要对goods.vue中的<shop-cart>绑定属性select-foods,如
<shop-cart :select-foods="selectFoods" :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"><Shop-cart>
selectFoods在goods.vue中的computed中的定义如下:
// 选中的商品,返回一个数组,数组的成员是有count属性的会是已经加入购物车的商品
selectFoods(){
let foods = [];
this.goods.forEach((good) => {
good.foods.forEach((food) => {
// 对每一个商品的count属性进行遍历
// count在cartControl.vue中有定义,会影响到父组件的
if(food.count){
// 证明该食品有添加到购物车
// 找到所有被选择的food
foods.push(food);
}
});
});
return foods;
}
}
count属性是在cartControl.vue中添加的,在子组件对父组件传递过来的数据的修改会反映到父组件上面,所以在父组件可以对每一样good下面的每一样的food遍历,当food下面有count属性的时候,说面该food已经被添加到购物车了
在shopCart.vue中需要对属性select-foods做声明:
注意: 在父组件good.vue中绑定属性用横划线的写法select-foods,而在s子组件shopCart.vue中声明该属性的时候,用的是驼峰写法selectFoods