将商品添加到购物车要先监听购物车点击
在DetailBottomBar.vue中监听
<div class="cart" @click="addToCart">加入购物车</div>
methods:{
addToCart(){
this.$emit('addCart');
}
}
然后在Detail.vue的detail-bottom-bar标签中
<detail-bottom-bar @addCart="addCart"></detail-bottom-bar>
在methods中
addToCart(){
//1.获取购物车需要展示的信息
const product={}
product.image=this.topImages[0]
product.title=this.goods.title;
product.desc=this.goods.desc;
product.price=this.goods.realPrice;
product.iid=this.iid;
}
我们需要从详情页拿到商品的数据,然后在购物车里面显示,所以我们可以通过Vuex
首先安装vuex
npm install vuex@3.5.1 --save
然后在store文件夹中新建index.js
import Vue from "vue";
import Vuex from "vuex";
//安装插件
Vue.use(Vuex);
//创建Store对象
const state = {
cartList: [],
};
const store = new Vuex.Store({
state,
mutations:{}
actions:{}
getters:{}
});
//挂载到Vuex实例上
export default store;
然后在main.js里面做一个导入。
再到
addToCart(){
//2、将商品添加到购物车
this.$store.cartList.push(product)
但是实际上能不能像上面这样做呢?不能,任何修改state里面的东西都要通过mutations
mutations:{
addCart(state, payload){
state.cartList.push(payload)
}
}
然后在Detail.vue的methods中
addToCart(){
//2、将商品添加到购物车
this.$store.commit('addCart',product)
}
在购物车里面还需要判断这个数据是否已经存在,类别不同,数量不能光往上加,还需要在mutations里面做判断
addCart(state, payload){
//1.查找之前数组是否有该商品
let oldProduce=state.cartList.find(item=>item.iid===payload.iid)
//2.判断oldProduce
if(oldProduce){
oldProduce.count+=1
}else{
payload.count=1
state.cartList.push(payload)
}
}
下面我们验证一下:
我们在detail中
<ul>
<li v-for="item in $store.state.cartList">{{item}}</li>
</ul>
最终的结果为:
总结:当我们点击添加购物车的时候,在方法中addCart方法先获取商品信息,再通过Vuex里的commit,调用的就是mutations里面的addCart,将商品拿到,然后判断之前有没有该商品,如果有的话,直接在之前的基础上加1,没有的话,设置其数量为1。
对上述代码进行简单的重构:
- mutations唯一的目的就是修改state的状态
- mutations中的每个方法进可能完成的事情比较单一一点。
但是在我们的mutations里面现在做了两件事情,既有可能是数量加1,又有可能是把一个新的商品添加进去。在我们的mutations的设计原则里面一般不让这样做,虽然这样做对代码来讲并没有影响,但是我们最好还是不要这样做。就让每个mutations做一件单一的事情。
一般情况下,第一步修改我们某个操作的时候,最好是通过action,再到mutations,再来修改state。
所以有判断逻辑的东西我们放到actions里面
actions:{
addCart(state, payload){
//1.查找之前数组是否有该商品
let oldProduce=state.cartList.find(item=>item.iid===payload.iid)
//2.判断oldProduce
if(oldProduce){
oldProduce.count+=1
}else{
payload.count=1
state.cartList.push(payload)
}
}
}
然后detail里面
this.$store.commit('addCart',product)
这一句就不能这么写了,要用到dispatch
this.$store.dispatch('addCart',product)
又dispatch第一个参数不是state,而是context,,所以有
addCart(context, payload){
//1.查找之前数组是否有该商品
let oldProduce=context.state.cartList.find(item=>item.iid===payload.iid)
//2.判断oldProduce
if(oldProduce){
oldProduce.count+=1
}else{
payload.count=1
context.state.cartList.push(payload)
}
}
再次进行优化
mutations:{
addCounter(state,payload){
payload.count++
},
addCart(state,payload){
state.cartList.push(payload)
}
},
actions:{
addCart(context, payload){
//1.查找之前数组是否有该商品
let oldProduce=context.state.cartList.find(item=>item.iid===payload.iid)
//2.判断oldProduce
if(oldProduce){
// oldProduce.count+=1
context.commit('addCounter',oldProduce)
}else{
payload.count=1
// context.state.cartList.push(payload)
context.commit('addCart', payload)
}
}
这样我们的vuex能更好的做跟踪。
接着我们接着再次做重构,新建mutations.js,action.js把它们相关的代码都抽出去。
index.js如下
import Vue from "vue";
import Vuex from "vuex";
import mutations from '@/store/mutations';
import actions from '@/store/actions'
Vue.use(Vuex);
const state = {
cartList: [],
};
const store = new Vuex.Store({
state,
mutations,
actions,
});
export default store;
接着我们还想将mutations中的addCounter,addCart抽成常量,新建mutation-types.js
export const ADD_COUNTER='add_counter'
export const ADD_CART='add_cart'
然后将其导入到actions和mutations
import {
ADD_COUNTER,
ADD_CART
} from './mutation-types'
export default {
addCart(context, payload){
//1.查找之前数组是否有该商品
let oldProduce=context.state.cartList.find(item=>item.iid===payload.iid)
//2.判断oldProduce
if(oldProduce){
// oldProduce.count+=1
context.commit('ADD_COUNTER',oldProduce)
}else{
payload.count=1
// context.state.cartList.push(payload)
context.commit('ADD_CART', payload)
}
}
}
import {
ADD_COUNTER,
ADD_CART
} from './mutation-types'
export default {
[ADD_COUNTER](state,payload){
payload.count++
},
[ADD_CART](state,payload){
state.cartList.push(payload)
}
}