在购物车组件中,定义一个判断是否全选 使用计算属性 使用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