14-案例:购物车

 综合案例-购物车

需求说明:

        1. 渲染功能

                v-if/v-else v-for :class

        2. 删除功能

                点击传参 filter过滤覆盖原数组

        3. 修改个数

                点击传参 find找对象

        4. 全选反选

                计算属性computed 完整写法 get/set

        5. 统计 选中的 总价 和 数量

                计算属性conputed reduce条件求和

        6. 持久化到本地 

                watch监听,localStorage, JSON.stringfiy, JSON.parse

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        .active {
            background-color: azure;
        }
    </style>

</head>

<body>
    <div id="app">
        <!-- 顶部banner -->
        <div><img></div>
        <!-- 面包屑 -->
        <div></div>

        <!-- 购物车主体 -->
        <div v-if="fruitList.length > 0">
            <div>
                <!-- 头部 -->
                <div>
                    <div>

                    </div>
                </div>
                <!-- 身体 -->
                <div>
                    <div v-for="(item,index) in fruitList" :key="item.id" :class="{active:item.isChecked}">
                        <div><input type="checkbox" v-model="item.isChecked"></div>
                        <div><img width="100px" height="50px" :src="item.icon"></div>
                        <div>{{item.price}}</div>
                        <div>
                            <div>
                                <!-- :disabled: 禁用 -->
                                <button :disabled="item.num<=1" @click="sub(item.id)">-</button>
                                <span>{{item.num}}</span>
                                <button @click="add(item.id)">+</button>
                            </div>
                        </div>
                        <div>{{ item.num * item.price }}</div>
                        <div><button @click="del(item.id)">删除</button></div>
                    </div>

                </div>
            </div>
            <!-- 底部 -->
            <div>
                <!-- 全选 -->
                <label>
                    <input type="checkbox" v-model="isAll">全选
                </label>
                <div>
                    <!-- 所有商品总价 -->
                    <span>总价:{{totalPrice}} </span>
                    <!-- 结算按钮 -->
                    <button>结算({{totalCount}})</button>
                </div>
            </div>
        </div>
        <!-- 空车 -->
        <div v-else>空空如也</div>

    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <script>
        // 购物车的默认值
        const defaultArr = [
                    {
                        id: 1,
                        icon: 'http://autumnfish.cn/static/火龙果.png',
                        isChecked: true,
                        num: 2,
                        price: 6
                    }, {
                        id: 2,
                        icon: 'http://autumnfish.cn/static/荔枝.png',
                        isChecked: false,
                        num: 7,
                        price: 20
                    }, {
                        id: 3,
                        icon: 'http://autumnfish.cn/static/榴莲.png',
                        isChecked: true,
                        num: 10,
                        price: 50
                    },
                ]
        const app = new Vue({

            el: '#app',
            data: {
                // 水果列表,从本地缓存读取,|| []: 初始值,一般都是空数组
                fruitList:  JSON.parse(localStorage.getItem("list")) || defaultArr,
            },
            computed: {
                // 默认计算属性:只能获取不能设置,要设置需要写完整的写法
                // isAll(){
                //     // 必须所有的小选框都选中,全选按钮才选中 -> every
                //     return  this.fruitList.every(item => item.isChecked === true)
                // }

                // 完整写法 = get + set
                isAll:{
                    get(){
                    return  this.fruitList.every(item => item.isChecked === true)

                    },
                    set(value){
                        // 基于拿到的布尔值,要让所有的小选框,同步状态
                        this.fruitList.forEach(item => item.isChecked = value)
                    }
                },
                // 统计选中的总数 reduce
                totalCount(){
                    return this.fruitList.reduce((sum,item) => {
                        if (item.isChecked){
                            // 选中 -> 需要累加
                            return sum + item.num
                        }else{
                            // 没选中 -> 不需要累加
                            return sum
                        }
                    },0)
                },
                // 统计选中的总价 num * price
                totalPrice(){
                    return this.fruitList.reduce((sum,item) => {
                        if (item.isChecked){
                            return sum + item.num * item.price
                        }else{
                            return sum
                        }
                    },0)
                }

            },

            methods: {
                del(id) {
                    this.fruitList = this.fruitList.filter(item => item.id != id)
                },
                sub(id) {
                    // 1. 根据ID找到数组中的对应项 -> find
                    const fruit = this.fruitList.find(item => item.id === id)

                    //2. 操作 num 数量
                    fruit.num--

                },
                add(id) {
                    // 1. 根据ID找到数组中的对应项 -> find
                    const fruit = this.fruitList.find(item => item.id === id)

                    //2. 操作 num 数量
                    fruit.num++
                }
            },

             // 缓存到本地
             watch:{
                fruitList:{
                    deep: true,
                    handler(newValue){
                        // 需要将变化后的 newValue 存入本地 (转json)
                        localStorage.setItem("list",JSON.stringify(newValue))
                    }
                }
            }
           
        })

    </script>


</body>

</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值