vuex实现购物车基本业务逻辑(移动端)
在本购物车业务中用到了第三方组件库vant,使用之前要先安装并导入相关依赖
安装vant
npm i vant -S
导入组件
我们这里直接导入了所有组件,但是vant也支持按需引入
import Vant from ‘vant’;
import ‘vant/lib/index.css’;
Vue.use(Vant);
添加商品
商品列表页面
<template>
<!-- shoppingList.vue -->
<!-- 点击购物车图标触发点击事件,并把商品传进去 -->
<span @click="addShoppingCart(item)"><van-icon name="shopping-cart-o" /></span>
</template>
<script>
methods: {
//点击事件 提交一个方法,在vuex中定义并处理
//这里提交的是一个同步的commit方法,异步的提交方法为dispacth
addShoppingCart(item){
this.$store.commit("addShoppingCart",item)
}
},
</script>
在vuex的index.js页面定义业务逻辑
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//取出本地存储保存的购物车数据
let cartItem = JSON.parse(localStorage.getItem("shoppingcart"))
//取出保存的全选按钮状态
let shoppingCartCheckAll = JSON.parse(localStorage.getItem("shoppingCartCheckAll"))
export default new Vuex.Store({
state: {
//定义购物车数组 如果本地取出则取本地,如果没有则取空
shoppingCartItem: cartItem?cartItem:[],
// 定义全选状态 如果本地取出则取本地,如果没有则取空
shoppingCartCheckAll:shoppingCartCheckAll?shoppingCartCheckAll:false
},
mutations: {
//定义添加购物车方法
addShoppingCart(state, item) {
//进行去重
let index = state.shoppingCartItem.findIndex(ele => {
return ele.id === item.id
})
//如果购物车中存在商品则让这个商品数量加1
if (index !== -1) {
state.shoppingCartItem[index].count += 1;
//不存在商品则添加提交的商品
} else {
//定义商品选中状态
item.checked = false
state.shoppingCartItem.push(item)
}
//添加完毕后保存到本地
localStorage.setItem("shoppingcart",JSON.stringify(state.shoppingCartItem))
},
}
购物车页面
全选状态切换
<template>
<div>
<!-- 定义一个商品格子子组件,并循环商品创建 -->
<ShoppingCartItem
v-for="(item,index) in data"
:key="index"
:item="item"
/>
<div class="shopping_cart_submit">
<van-submit-bar :price="this.$store.getters.totalPrice*100" button-text="提交订单">
<!-- 全选按钮的状态在vuex中定义 -->
<van-checkbox
v-model="test"
>全选</van-checkbox>
</van-submit-bar>
</div>
</div>
</template>
<script>
import ShoppingCartItem from "../components/ShoppingCartItem";
export default {
components: {
ShoppingCartItem
},
data() {
return {
//接收vuex中的购物车商品列表数据
data: this.$store.state.shoppingCartItem,
};
},
// 由于vue中input的值双向绑定的数据必须在data中定义,所以采用计算属性的get和set定义双向绑定的值
computed: {
test:{
// get方法获取vuex的数据并return
get(){
return this.$store.state.shoppingCartCheckAll
},
//set方法接收一个参数,这个参数就是绑定的布尔值
//set会改变传过来的值
set(v){
//window.console.log(v)
//提交一个方法 在vuex中定义并处理
this.$store.commit("oncheckAll",v);
}
}
},
};
</script>
<style scoped>
.van-submit-bar {
position: fixed;
margin-bottom: 64px;
}
</style>
全选状态切换业务逻辑
这里为了节省代码就不写其余业务的代码了
mutation:{
oncheckAll(state,boolean) {
//循环购物车数组。并把全选按钮的值赋值给商品的选中状态
state.shoppingCartItem.forEach(ele=> (ele.checked = boolean))
//保存到本地
localStorage.setItem("shoppingCartCheckAll",JSON.stringify(state.shoppingCartCheckAll))
localStorage.setItem("shoppingcart",JSON.stringify(state.shoppingCartItem))
}
}
商品选中状态切换
商品组件
<template>
<div>
<van-card
:num="item.count"
:price="item.price*item.count"
:title="item.content"
:thumb="item.image"
>
<div slot="tags">
<!-- 商品选中状态在添加商品时候添加进了商品对象中 双向绑定商品选中状态 提交一个方法 -->
<van-checkbox v-model="item.checked" @change="onCheckItem"></van-checkbox>
</div>
<div slot="footer">
<!-- 定义商品数量加减方法 -->
<van-stepper v-model="item.count" @plus="addCount" @minus="minCount" />
</div>
</van-card>
</div>
</template>
<script>
export default {
props: {
item: Object
},
data() {
return {
};
},
methods: {
// 提交一个处理方法 在vuex中定义并处理
onCheckItem() {
this.$store.commit("onCheckItem");
},
// 商品数量加减方法
addCount() {
this.$store.commit("addCount", this.item);
},
minCount() {
this.$store.commit("minCount", this.item);
}
}
};
</script>
商品选中状态切换逻辑
mutation:{
onCheckItem(state){
// 定义一个临时数组
let tempArr = []
// 循环购物车数组,并且添加进定义的空数组
state.shoppingCartItem.forEach(ele=>{
tempArr.push(ele)
})
// every循环定义的临时数组
// every()方法,针对数组中的每一个元素进行比对
// 只要有一个元素比对结果为false则返回false
// 反之要所有的元素比对结果为true才为true
let result = tempArr.every(ele=>{
// 对数组中每一项的选中状态比较 是否为选中状态 也就是true
return ele.checked == true
})
// 全选按钮的选中状态等于every方法返回的值
// 如果返回true说明商品全部选中 反之则说明有未选中的
// 所以可以直接让全选按钮的值等于every方法返回的数据
state.shoppingCartCheckAll = result
// 保存到本地
localStorage.setItem("shoppingCartCheckAll",JSON.stringify(state.shoppingCartCheckAll))
// 保存本地
localStorage.setItem("shoppingcart",JSON.stringify(state.shoppingCartItem))
},
}
商品数量加减
addCount(state,item){
item.count++
localStorage.setItem("shoppingcart",JSON.stringify(state.shoppingCartItem))
},
minCount(state,item){
item.count--
localStorage.setItem("shoppingcart",JSON.stringify(state.shoppingCartItem))
},
}
商品总价计算
vuex中也有一个类似vue计算属性的方法 getters,我们可以在这里进行一些类似于计算属性的操作
getters: {
// 总价计算
totalPrice(state) {
// 声明一个变量
let totalPrice = 0
// 循环购物车数组
state.shoppingCartItem.forEach(ele => {
// 如果选中则累加商品价格*商品数量
if(ele.checked == true){
totalPrice += ele.count * ele.price
}
})
// 导出
return totalPrice
}
在vue中可以直接使用getters方法导出的数据
<template>
<van-submit-bar :price="this.$store.getters.totalPrice*100" button-text="提交订单">
</template>
这样一个购物车的基础功能就实现啦