Vuex是一个应用状态管理库。当涉及大量状态需要多个组件共享时,可以采用Vuex。当进行一些小项目开发时,涉及组件传值时,或者项目非常小,组件间共享状态不多的情况下,此时可以使用简单的store模式或者其它方式。
在一些中大型单页应用程序中,需要解决多个视图依赖同一状态,来自不同视图的行为需要变更同一状态的问题,所有满足这两个条件的项目和业务,建议使用Vuex进行状态管理。
典型的购物车案例,涉及多个子组件依赖同一个状态和来自不同视图的一些行为需要改变同一个状态值。此案例主要实现商品列表的显示,主要有增加和删除商品、增加和减少商品数量、实时显示购物车里面总的商品数量和总价格。
使用时,需要将商品列表组件Product.vue和购物车列表组件Cart.vue在App.vue中引入,并在Vuex的store文件夹下的cart.js中定义好商品数据 all_products和已添加到购物车的商品数据selected,然后将该模块放入index.js文件的modules对象中,将数据通过getters导出,将方法通过actions和mutations导出。
cart.js文件代码如下:
// store/cart.js
//所有购物车共享数据
const state={
//商品数据
all_products: [
{ id:1,name: '电视',price: 5000},
{ id:2,name: '冰箱',price: 8000},
{ id:3,name: '平板',price: 6000},
{ id:4,name: '手机',price: 1500},
{ id:5,name: '耳机,price: 120},
],
//已选的商品数据
selected: []
}
//将数据导出
const getters={
//商品数据
products: state=>state.all_products,
//购物车中数据
cartProducts: state=>{
return state.selected.map(item=>{
let curProducts=state.all_products.find(i=>i.id===item.id);
let count=item.count;
return {
...curProducts,count
}
})
},
//总价
totalPrice: (state,getters)=>{
let total=0;
getters.cartProducts.forEach(item=>{
total+=item.price*item.count;
});
return total;
},
//已选商品总数量
totalCount: (state,getters)=>{
let total=0;
getters.cartProducts.forEach(item=>{
total+=item.count;
});
return total;
}
}
const mutations={
//添加商吕数据
addTo(state,{id}){
//判断是否添加过该商品
let curProduct=state.selected.find(item=>item.id===id);
if(!curProduct){
//未添加过,直接加入已选商品数组中
state.selected.push({
id,count: 1
});
} else {
//已经添加过,直接将数量加一
curProduct.count++;
}
},
//清空操作
clear(state){
state.selected=[]
},
//减去一个商品
delOne(state,{id}){
let curIndex=state.selected.findIndex(item=>item.id===id);
if(state.selected[curIndex].count>0){
state.selectd[curIndex].count--;
} else if(state.selected[curIndex].count==0){
//商品数量为0直接删除
state.selected.splice(curIndex,1);
} else { return ; }
},
//添加一个商品
addOne(state,{id}){
let curIndex=state.selected.findIndex(item=>item.id===id);
staate.selected[curIndex].count++;
}
};
//处理异步操作
const actions={
//添加商品进入购物车
addCart({commit},product){
//添加时传入商品的id
commit('addTo',{id: proudct.id})
},
//清空购物车
clearCart({commit}){
commit('clear')
},
//减去一个商品
delOne({commit},product){
commit('delOne',{id: product.id});
},
//增加一个商品
addOne('commit',{id: product.id}){
commit('addOne',{id: product.id });
}
};
//导出各个对象
export default {
state,getters,mutations,actions
}
在以上代码中分别定义了商品数据all_products,添加到购物车的数据selected,getters中导出的products和cartProducts数据,还定义了添加商品addOne,减少商品delOne,添加购物车addCart 清空购物车clearCart等方法。
商品列表组件product.vue
//Product.vue
<template>
<div class='product'>
<h3>商吕展览</h3>
<table class='table' border>
<thead>
<tr>
<td>id</td>
<td>名称</td>
<td>价格</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for='item in products ' :key='item.id'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><button @click="addCart(item)">添加</button></td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {mapGetters,mapActions} from 'vuex'
export default {
name: 'Product',
data() { return {} },
computed: {
//从store中取出数据
...mapGetters(['products'])
},
methods: {
...mapActions(['addCart'])
}
}
</script>
购物车列表cart.vue组件
//cart.vue
<template>
<div class='cart'>
<h3>已选商吕</h3>
<div v-if="cartProducts.length">
<table class='table' border>
<thead>
<tr>
<td>id</td>
<td>名称</td>
<td>价格</td>
<td>数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for='item in cartProducts ' :key='item.id'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.count}}</td>
<td>
<div>
<button @click="addOne(item)">+</button>
<button @click="delOne(item)">-</button>
</div>
</td>
</tr>
</tbody>
</table>
<div @click="clearCart">清空购物车</div>
<div>
<p>您已经选择{{totalCount}}件商品,总计{{totalPrice}}元</p>
</div>
<div v-else>您暂未选取任何商品...</div>
</div>
</template>
<script>
import {mapGetters,mapActions} from 'vuex'
export default {
name: 'Cart',
props: {},
data() { return {} },
methods: {
...mapActions(['clearCart','delOne','addOne'])
},
computed: {
...mapGetters(['clearProducts','totalPrice','totalCount'])
}
}
</script>
最后在App.vue中引入两个组件,代码如下:
<template>
<div>
<Product></Product>
<Cart></Cart>
</div>
</template>
<script>
import Product from './comments/Product.vue'
import Cart from './comments/Cart.vue'
export default {
name: 'App',
components: {
Product,Cart
}
}
</script>
代码主要通过mapGetters方法和mapActions方法将store中的方法提取,在vue文件中使用,最终购物车项目运行效果如下所示。
单击‘清空购物车’按钮时出现的效果如下所示:
以下就是使用Vuex进行购物车功能开发,读者可以在此基础上进行样式、界面等的美化,还可以以此增加功能。