您的位置:首页 > Web前端 > Vue.js

vue+vuex实现购物车功能

2019-08-12 10:36 357 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/lei_0912/article/details/99289563

主要是实现了加入购物车,单选,全选,数量加减,删除等功能


一、逻辑代码

import Vue from 'vue';
import Vuex from 'vuex';
import Toast from '@nutui/nutui/dist/packages/toast/toast.js';
import Dialog from '@nutui/nutui/dist/packages/dialog/dialog.js';

Vue.use(Vuex);

const store=new Vuex.Store({
// 设置全局要访问的state值
state:{
car:localStorage["car"]?JSON.parse(localStorage["car"]): [] ,  //购物车,涉及到刷新数据丢失,所以存了本地
all_money:0, //总价
all_selsect:true, //全选状态
},
// 实时监听state值的变化
getters:{
//购物车列表
carList(state){
// 初始化全选状态
if(state.all_selsect){
state.car.forEach((item)=>{
item.selected=true
})
}
列表变化存本地
localStorage.setItem("search",JSON.stringify(state.car));
return state.car
},
//选中商品的金额
allMoney(state){
let all_money=0
state.car.forEach((item)=>{
if(item.selected){
all_money+=item.num*item.sellPrice
}
})
return state.all_money=all_money
},
},
// 改变state里的初始值 同步的
mutations :{
//添加商品
ADDGoods(state,data){
let datas={       //传入的商品属性
title:data.title,
img:data.pictures[0],
num:1,
sellPrice:data.sellPrice,
marketPrice:data.marketPrice,
selected:true,
productId:data.productId
}
let index=-1
index=state.car.findIndex(item=>{     //返回元素的索引位置,如果没有符合条件的元素返回 -1
return item.productId==data.productId
})
if(index==-1){    //返回-1说明购物车里没有这个商品,则push进去,如果返回下标,则让此商品的数量加1
state.car.push(datas)
}else{
state.car[index].num++
}
Toast.success('添加成功!');
},
//购物车页面数量加减
ADDNUM(state,productId){
let index=state.car.findIndex(item=>{
return item.productId==productId
})
return state.car[index].num++
},
//购物车页面数量加减
JIANNUM(state,productId){
let index=state.car.findIndex(item=>{
return item.productId==productId
})
if(state.car[index].num<=1){
return state.car[index].num=1
}else{
return state.car[index].num--
}
},
//购物车单选
SELECT(state,productId){
let index=state.car.findIndex(item=>{
return item.productId==productId
})
state.car[index].selected=!state.car[index].selected
let flag=state.car.some((item)=>{
return item.selected==false
})
if(!flag){       //如果全部选中,则全选状态也改变
state.all_selsect=true
}else{
state.all_selsect=false
}
},
// 购物车全选
SELECTALL(state){
state.all_selsect=!state.all_selsect
if(state.all_selsect){
state.car.forEach((item)=>{
item.selected=true
})
}else{
state.car.forEach((item)=>{
item.selected=false
})
}
},
//删除选中的商品,注意这里不能使用数组删除的方法,索引值会有问题
DEL(state){
let flag=state.car.some((item)=>{
return item.selected==true
})
if(!flag){
Toast.text('请至少选择一个商品')
}else{
Dialog[0]({
title:'确定从购物车中删除吗?',
onOkBtn() {  //确定按钮点击事件
this.close(); //关闭对话框
var list=[];
state.car.forEach((item,index)=>{
if(!item.selected){
list.push(item)
}
})
return state.car=list
},
})
}
},
},
// 异步触发mutations里面的方法 在外部组件里进行全局执行actions里面方法的时候,你只需要用执行this.$store.dispatch('headTitle',132) 这样就可以全局改变改变标题的值了
actions:{
addGoods({commit},data){
commit('ADDGoods',data)
},
addNum({commit},id){
commit('ADDNUM',id)
},
jianNum({commit},id){
commit('JIANNUM',id)
},
select({commit},id){
commit('SELECT',id)
},
selectAll({commit}){
commit('SELECTALL')
},
del({commit}){
commit('DEL')
},
}
})

3ff7
export default store;

二、加入购物车

<template>
<div class='addCar' @click="addCar" >加入购物车</div>
</template>

import { mapActions } from 'vuex'    //引入方法
//方法集合
methods: {
...mapActions(['addGoods']),   //es6的扩展运算符
// 加入购物车
addCar:function(){
this.addGoods(this.info)
}
},

三、购物车页面

<!--  -->
<template>
<div class='car'>
<div class='edit'>
<p class='edit-text edit-texts' @click='del_show=false' v-if='del_show' >完成</p>
<p class='edit-text ' @click="del_show=true" v-else>编辑</p>
</div>
<div class='car-box'>
<div class='car-list' v-for='(item,index) in carList'  :key='index'>
<img src="../../../static/image/radios.png" alt="" class='choose-icon'  v-if='item.selected' @click='select(item.productId)'>
<img src="../../../static/image/radio.png" alt="" class='choose-icon' v-else @click='select(item.productId)'>
<img :src="item.img" alt="" class='car-img' >
<div class='car-fr'>
<div class='car-name'>{{item.title}}</div>
<div class='fr-btm'>
<div class='car-money'>
<p class='money-old'>¥{{item.marketPrice}}</p>
<p class='money-now'>¥{{item.sellPrice}}</p>
</div>
<div class='car-num'>
<img src="../../../static/image/jian1.png" alt="" class='num-icon'  v-if='item.num==1'>
<img src="../../../static/image/jian.png" alt="" class='num-icon' @click='jianNum(item.productId)' v-else>
<span class='car-nums'>{{item.num}}</span>
<img src="../../../static/image/jia.png" alt=""  class='num-icon' @click='addNum(item.productId)' >
</div>
</div>

</div>
</div>
</div>
<div class='car-btm'>
<div class='btm-fl' @click="selectAll()">
<img src="../../../static/image/radios.png" alt="" class='choose-icon' v-if='allSelsect' >
<img src="../../../static/image/radio.png" alt="" class='choose-icon' v-else >
<span class='all-text'>全选</span>
</div>
<div class='all-money'>共计:¥{{allMoney}}</div>
<div class='del' v-if='del_show' @click="del()">删除</div>
<div class='pay' v-else>结算</div>
</div>
</div>
</template>

<script>
import { mapActions ,mapGetters} from 'vuex'
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {
del_show:false
};
},
//监听属性 类似于data概念
computed: {   //computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理;
...mapGetters(['carList','allMoney','allSelsect'])
},
//监控data中的数据变化
watch: {},
//方法集合
methods: {
...mapActions(['headTitle','addNum','jianNum','select','selectAll','del','showBtm'])
},
//生命周期 - 创建完成(可以访问当前this实例)
created() {
},
//生命周期 - 挂载完成(可以访问DOM元素)
mounted() {

},
beforeCreate() {}, //生命周期 - 创建之前
beforeMount() {}, //生命周期 - 挂载之前
beforeUpdate() {}, //生命周期 - 更新之前
updated() {}, //生命周期 - 更新之后
beforeDestroy() {}, //生命周期 - 销毁之前
destroyed() {}, //生命周期 - 销毁完成
activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
}
</script>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: