Vuex实现完整购物车

举报
达拉崩巴斑得贝迪卜多 发表于 2021/12/24 15:10:58 2021/12/24
【摘要】 Vuex实现完整购物车功能描述加购全选 反选数量加减总价 总量删除本地存储效果展示一:点击加入购物车页面 详见 加购页面二:购物车页面lookCart知识点: 过滤器<template> <div> <van-nav-bar title="购物车" left-text="返回" left...

Vuex实现完整购物车

功能描述

  • 加购
  • 全选 反选
  • 数量加减
  • 总价 总量
  • 删除
  • 本地存储

效果展示
在这里插入图片描述

一:点击加入购物车页面 详见 加购页面

二:购物车页面lookCart
知识点: 过滤器

<template>
   <div>
       <van-nav-bar
               title="购物车"
               left-text="返回"
               left-arrow
               @click-left="onClickLeft"
               @click-right="changeEditDone"
       >
           <template #right>
                   <span v-if="editDone"> 编辑 </span>
                   <span v-if="!editDone"> 完成 </span>
           </template>
       </van-nav-bar>

       <div class="detail_wrapper">
            <div v-for="(item,index) in MediaCart" :key="index">
                <div class="detail_item">
                    <input type="checkbox" :checked ='item.checked' @click="changeCheckbox(item)">
                    <img :src="item.productImage"  class="productImage">
                    <p>{{item.productName}}</p>
                    <p>{{item.salePrice}}</p>
                    <van-stepper v-model="item.count" theme="round" button-size="22" disable-input  @change="addReduceChange"/>
                </div>
            </div>
       </div>

<!--       尾部 全选 总价-->
       <footer>
            <div class="footer_left">
                <input type="checkbox" :checked="allSelected" @click="All">  全选
            </div>
           <div class="footer_right">
               <div v-if="editDone">
                   <span>数量: {{totalCount}}</span>
                   <span>总价:{{totalPrice | priceFilter}}</span>
               </div>
               <div v-if="!editDone">

                   <van-button icon="delete"  plain type="info" @click="delSelect">删除</van-button>
               </div>



           </div>
       </footer>
   </div>
</template>

<script>
    import Header from "../../../../job/src/components/comment/Header";   // 引入头部公共组件
    export default {
        name: "lookCart",
        components:{Header},
        data(){
            return{
                editDone:true
            }
        },
        computed:{
            //购物车里的数据
            MediaCart(){
                return this.$store.state.MediaCartVuex.MediaCart
            },
            //从vuex中获取到全选状态
            allSelected(){
                return this.$store.state.MediaCartVuex.allSelected
            },
            // 从vuex中获取到总共数量
            totalCount(){
                return this.$store.state.MediaCartVuex.totalCount
            },
            // 从vuex中获取到总价钱
            totalPrice(){
                return this.$store.state.MediaCartVuex.totalPrice
            },

        },
        mounted(){
            // 挂载后 根据当前的状态 执行 计算总价
            this.$store.dispatch('calculationPriceCount')
        },
        methods:{
            //改变每个复选框的状态
            changeCheckbox(item){
                //触发 vuex 里的事件  传递的参数 只需要 id  以及 选中状态
                this.$store.dispatch('changeCheckbox',{id:item._id, checked:event.target.checked})
            },
            //点击全选 联动复选框
            All(){
                let boolean = event.target.checked;
                this.$store.dispatch('All',boolean)
            },
            //点击+- 时候 变化
            addReduceChange(){
                this.$store.dispatch('calculationPriceCount')
            },
            //点击左箭头 返回
            onClickLeft(){
                window.history.back()
            },
            //点击完成 编辑按钮
            changeEditDone(){
                this.editDone = !this.editDone
            },
            //点击删除
            delSelect(){
                this.$dialog.confirm({
                    message: '确认删除',
                }).then(() => {
                    //删除之后要变为 '编辑'
                    this.editDone = !this.editDone;
                    //异步调用 删除 方法
                    this.$store.dispatch('delSelect');
                    // 调用 总价  --更新总价
                    this.$store.dispatch('calculationPriceCount');
                    // 更新全选框 在状态 为 不选中 false
                    this.$store.dispatch('All',false)
                }).catch(() => {
                        // on cancel
                });

            }
        },
        // 局部过滤器
        filters:{
            priceFilter(text){
               return '¥' + text.toFixed(2)
            }
        }

    }
</script>

<style scoped>
    footer {
        width: 100%;
        height: 100px;
        background-color: #F5F5F5;
        position: absolute;
        bottom: 0;
        left: 0;
        z-index: 888;
        display: flex;
        justify-content: space-between;
        padding: 20px 200px;
        box-sizing: border-box;
        align-items: center;
    }
    .detail_item {
        width: 100%;
        display: flex;
        justify-content: space-around;
        align-items: center;
        border:1px solid #eee;
        margin-bottom: 10px;
    }
    .productImage {
        width: 100px;
    }
    .detail_wrapper {
        width: 100%;
        height: 100%;
        padding: 50px;
        box-sizing: border-box;
    }

</style>

三: 逻辑代码 vuex MediaCartVuex

const MediaCartVuex ={
    state: {
        MediaCart: JSON.parse(localStorage.getItem('addMediaCart'))  || [],  //购物车的数据保存数组
        allSelected: JSON.parse(localStorage.getItem('all')) ||  false, //定义全选状态
        totalCount:0, //总共数量
        totalPrice:0, //总价钱
    },
    mutations: {
        //1.加购去重
        addMediaCart(state,item){
           let index =state.MediaCart.findIndex(ele=>{
               return ele.productId === item.productId
           });
           if(index === -1) {
               //自定义数量 和状态
               item.count = 1;
               item.checked = false;
               state.MediaCart.push(item)
           }else {
               state.MediaCart[index].count++;
           }
           //本地存储
            localStorage.addMediaCart = JSON.stringify(state.MediaCart);
            //本地存储  全选框状态
            localStorage.all =  JSON.stringify(state.allSelected);
        },
        //2.改变复选框的状态
        changeCheckbox(state,item){
            //遍历数组  通过id找到对应的元素  然后改变checked值
            state.MediaCart.forEach(ele=>{
                if(ele._id === item.id){
                    ele.checked = item.checked
                }
            });
            //本地存储
            localStorage.addMediaCart = JSON.stringify(state.MediaCart);

            //全选状态-------------------------------------------
            state.allSelected =  state.MediaCart.every(ele=>{
                return ele.checked === true;
            });
            //本地存储 全选框的状态
            localStorage.all = JSON.stringify(state.allSelected);

            //计算价格总价---------------------------------------------
            state.totalCount = 0 ;  //先清0
            state.totalPrice = 0 ;  //先清0
            state.MediaCart.forEach(ele=>{
                 if(ele.checked){
                     state.totalCount += ele.count;
                     state.totalPrice += ele.count * ele.salePrice;
                 }
            });

        },
        //3.点击全选按钮  联动复选框
        All(state,boolean){
            //全选的状态为 传递过来 的boolean值
            state.allSelected = boolean;
            //遍历购物车数组
            state.MediaCart.forEach(ele=>{
                //让每个checked 为当前传过来的 boolean值
                ele.checked = boolean
            });
            //本地存储 购物车数据
            localStorage.addMediaCart = JSON.stringify(state.MediaCart);
            //本地存储  全选框状态
            localStorage.all = JSON.stringify(state.allSelected);

            //计算价格总价---------------------------------------------
            state.totalCount = 0 ;  //先清0
            state.totalPrice = 0 ;  //先清0
            state.MediaCart.forEach(ele=>{
                if(ele.checked){
                    state.totalCount += ele.count;
                    state.totalPrice += ele.count * ele.salePrice;
                }
            });
        },
        //4.计算总价 数量
        calculationPriceCount(state){
            //计算价格总价---------------------------------------------
            state.totalCount = 0 ;  //先清0
            state.totalPrice = 0 ;  //先清0
            state.MediaCart.forEach(ele=>{
                if(ele.checked){
                    state.totalCount += ele.count;
                    state.totalPrice += ele.count * ele.salePrice;
                }
            });

            //本地存储
            localStorage.addMediaCart = JSON.stringify(state.MediaCart);
        },
        //5.点击删除按钮
        delSelect(state){
            //  filter  检测数值元素,并返回符合条件所有元素的数组。
             let arr =    state.MediaCart.filter(ele=>{
                    return ele.checked === true
                });
            //此时的arr是已经被选中的元素
            //从原数组中 删除 arr 数组
            for(var i = 0;i < arr.length; i++) {
                for(var j = 0; j < state.MediaCart.length; j++) {
                    if(state.MediaCart[j] === arr[i]) {
                        state.MediaCart.splice(j,1);
                        j--;
                    }
                }
            }
            //本地存储
            localStorage.addMediaCart = JSON.stringify(state.MediaCart);
        }

    },
    actions: {
        //1.加购去重
        addMediaCart(context,item){
            context.commit('addMediaCart',item)
        },
        //2.改变复选框的状态
        changeCheckbox(context,item){
            //用item接收参数  -- id --选中状态
            context.commit('changeCheckbox',item)
        },
        //3.点击全选按钮  联动复选框
        All(context,boolean){
            context.commit('All',boolean)
        },
        //4.计算总价 数量
        calculationPriceCount(context){
            context.commit('calculationPriceCount')
        },
        //5.点击删除按钮
        delSelect(context){
            context.commit('delSelect')
        }
    },
    modules: {
    }
};
export default MediaCartVuex;
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。