前端实现购物车逻辑

在购物车组件中,定义一个判断是否全选 使用计算属性 使用get 和set方法 在get中判断在仓库购物车的数组里的sale属性是否位true使用数组方法ever 全部勾选返回true反之亦然,改变是否勾选课程使用set方法接收一个布尔值遍历数组把sale属性改成传过来的值

在购物车页面中,将计算出来的总价展示出来,

当用户修改了商品数量时,需要重新计算总价。可以通过监听商品数量变化的事件计算属性,在事件处理函数中重新计算总价

当用户修改商品数量时,会更新购物车中对应商品的数量,并通过reduce方法重新计算总价。最后将计算出来的总价赋值给total属性,从而实现实时更新总价的效果。

<template >
    //storeCart.list.length 仓库购物车的数组的长度  判断是否显示还是显示空空如也
    <div v-show="storeCart.list.length">
        <div class="cart-box">
            <!-- 购物车列表 -->
            <div class="swipe-wraper">
                <!-- 单元格 -->
                <!-- 滑动单元格  van-swipt-cell -->
                <van-swipe-cell v-for="item in storeCart.list" :key="item.goodsId">
                    <template #right>
                        <van-button class="delete-button" square type="danger" text="删除" @click="cartdel(item.id)" />
                    </template>
                    <template #default>
                        <div class="goods">
                            <!-- 复选框 -->
                            <van-checkbox class="btn" v-model="item.sale"></van-checkbox>
                            <!-- 个数 价格 名称 图片-->
                            <van-card class="goods-card" :num="item.count"
                                :price="((item.goods_info.price * item.count) / 100).toFixed(2)"
                                :desc="item.goods_info.name" :thumb="item.goods_info.pic_url">
									//名称
                                <template #tags>
                                    <van-tag type="primary">{{ item.goods_info.tags }}</van-tag>
                                </template>
									// 数量  计数器
                                <template #num>
                                    <van-stepper @change="change(item)" v-model="item.count"></van-stepper>
                                </template>
                            </van-card>
                        </div>

                    </template>
                </van-swipe-cell>
            </div>

        </div>
        <!-- 底部  -->
        <van-submit-bar :price="total" button-text="结算" v-show="storeCart.list.length" @submit='onSubmit'>
            <van-checkbox :checked="isAllChe" v-model="checkAll">全选</van-checkbox>
            <template #tip>
                你的收货地址不支持同城送, <span>修改地址</span>
            </template>
        </van-submit-bar>
    </div>


</template>

<script setup>
import { ref, computed } from "vue";
import useCartInfo from "@/stores/useCartInfo";
import { showConfirmDialog, showSuccessToast } from "vant";
import { cartAdd, cartEdit, cartDelete } from "@/api/cellect.js";
let storeCart = useCartInfo()
// 删除购物车
const cartdel = (id) => {
    showConfirmDialog({
        title: '确认删除',
        message:
            '是否确认删除 该商品。',
    })
        .then(async () => {
            // on confirm
            await cartDelete({ ids: id })
            storeCart.getCartInfo()
            showSuccessToast('删除商品成功')
        })
        .catch(() => {
            // on cancel
        });


}
// 计数器
const change = async (item) => {
    //改变商品的信息
    // 编辑购物车
    //调用修改 购物车接口 传递 当前商品在购物车内的id 商品id 和修改的数量
    let res = await cartEdit({ id: item.id, goods_id: item.goods_id, count: item.count })
    console.log('res: ', res);
}

// 总价 使用计算属性
const total = computed(() => {
    return storeCart.list.reduce((p, c) => p + (c.goods_info.price), 0)
})
// checkAll  全选与反选
let checkAll = computed({
    get() {
        // 商品复选框  sale是否勾选全选复选框
        //如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
		//如果所有元素都满足条件,则返回 true。
        return storeCart.list.every(item => item.sale)
    },
    set(val) {
        // 全选按钮  改变按钮状态
        return storeCart.list.forEach(item => item.sale = val)
    }
})
</script>

<style lang="scss" scoped>
.swipe-wraper {
    padding-bottom: 120px;

    .delete-button {
        height: 100%;
    }

    .goods {
        display: flex;
        margin: 5px;

        .van-checkbox {
            padding: 0 10px;
        }

        .van-card {
            width: 90%;
            margin-top: 0px;
        }
    }
}

.van-submit-bar {
    margin-bottom: 50px;
}
</style>

由于仓库 会在浏览器刷新时 数据被清空
会在app组件 渲染完成时 调用接口获取 最新的 购物车数据
直接 在生成订单页面组件 生命周期内 获取购物车仓库的 数据 拿不到 因为上面的接口需要时间 数据还没拿到

任何生命周期都不能 保证 比接口快 或者慢
由于 不能 保证 刷新页面时 在生命周期内 能够拿到接口返回的 仓库数据
所以 不要再 onMounted 内 拿我们的购物车数据

在监听内 我们监听 仓库的 list 变化后 去拿 我们的购物车数据又使用watch 监听 正常跳转至页面 不会触发仓库list更新 没办法 执行内部的过滤逻辑

最优选择 watchEffect 内去拿仓库list数组 过滤出 选中的购物车数据

watchEffect是立即执行的,在页面加载时会主动执行一次,来收集依赖;而watch是惰性地执行副作用,它不会立即执行,但可以配置 immediate,使其主动触发

import { defineStore } from "pinia";
import { cartList } from "@/api/cellect.js";

const useCartInfo = defineStore('cart', {
    state: () => {
        return {
            count: 0,
            list: []
        }
    },
    actions: {
        // 购物车信息 
        async getCartInfo() {
            const res = await cartList({ page: 1, limit: 100 })
            this.count = res.data.count
            this.list = res.data.list
        },
    }
})

export default useCartInfo
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值