vue+vuex实现购物车功能

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

在这里插入图片描述在这里插入图片描述在这里插入图片描述
一、逻辑代码

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("car",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
        },
        allSelsect(state){
            return state.all_selsect
        }
    },
    // 改变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')
        },
    }
})

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>

项目地址:https://github.com/zylgt/vue-cart.git

  • 25
    点赞
  • 137
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值