Vue 实现 购物车 案例

成品展示在这里插入图片描述

案例分析

  1. 按照组件化方式实现业务需求
  • 根据业务功能进行组件化划分
    ① 标题组件(展示文本)
    ② 列表组件(列表展示、商品数量变更)
    ③ 结算组件(计算商品总额)
    在这里插入图片描述

实现步骤

第一步

  1. 静态布局
  2. 将静态数据重构为Vue组件化的形式(通过Vue.component实现 )
  3. 在全局组件内 使用局部组件将其三部分分开(components)
  4. 实现组件化重构

第二步

  1. 用data 和props 实现动态数据传递
  2. 实现计算功能(第三属性 computed)
  3. 计算公式 总价= 单价 *数量
  4. v-for 循环并填充列表
  5. 在子组件获取id 传递给 子组件(this.$emit() 并在父组件进行监听)
  6. 设置删除按钮 ( 找到id 对应的数据的索引 使用splice 来删除对应的数据 )

第三步

  1. 使 数量显示在页面中
  2. 通过$event 来获取 id 和值 (event.target.value)
  3. 判断是要修改那个索引的数据
  4. 数据加减
  5. 使用@click绑定事件并且禁止a标签跳转功能
  6. 给加号 减号 设置一个标志 来相互区别(输入域变更,加号变更,减号变更)

用专业术语讲就是

  • 实现整体布局和样式效果
  • 划分独立的功能组件
  • 组合所有的子组件形成和整体结构
  • 逐个实现各个组件功能
    • 标题组件
    • 列表组件
    • 结算组件

基本样式

#app {
    
    
            width: 700px;
            height: 800px;
            margin: 0 auto;
        }

        .container .cart {
    
    
            width: 300px;
            margin: auto;
        }

        .container .title {
    
    
            background-color: lightblue;
            height: 40px;
            line-height: 40px;
            text-align: center;
            /*color: #fff;*/
        }

        .container .total {
    
    
            background-color: #FFCE46;
            height: 50px;
            line-height: 50px;
            text-align: right;
        }

        .container .total button {
    
    
            margin: 0 10px;
            background-color: #DC4C40;
            height: 35px;
            width: 80px;
            border: 0;
        }

        .container .total span {
    
    
            color: red;
            font-weight: bold;
        }

        .container .item {
    
    
            height: 55px;
            line-height: 55px;
            position: relative;
            border-top: 1px solid #ADD8E6;
        }

        .container .item img {
    
    
            width: 45px;
            height: 45px;
            margin: 5px;
        }

        .container .item .name {
    
    
            position: absolute;
            width: 90px;
            top: 0;
            left: 55px;
            font-size: 16px;
        }

        .container .item .change {
    
    
            width: 100px;
            position: absolute;
            top: 0;
            right: 50px;
        }

        .container .item .change a {
    
    
            font-size: 20px;
            width: 30px;
            text-decoration: none;
            background-color: lightgray;
            vertical-align: middle;
        }

        .container .item .change .num {
    
    
            width: 40px;
            height: 25px;
        }

        .container .item .del {
    
    
            position: absolute;
            top: 0;
            right: 0px;
            width: 40px;
            text-align: center;
            font-size: 40px;
            cursor: pointer;
            color: red;
        }

        .container .item .del:hover {
    
    
            background-color: orange;
        }

实现功能主要代码

<div id="app">
        <my-cart></my-cart>
    </div>

    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript">
        var CarTitle = {
     
     
            props: ['uname'],
            template: `
        <div class='title'>{
      
      {uname}}的商品</div>
        `
        }
        var CarList = {
     
     
            props: ['list'],
            template: ` 
         <div>
                <div :key='item.id' v-for='item in list' class="item">
                    <img :src="item.img">
                    <div class='name' >{
      
      {item.name}}</div>
                    <div class="change">
                        <a href="" @click.prevent='sub(item.id)'>—</a>
                        <input type="text" class="num" :value='item.num' @blur='changeNum(item.id,$event)' />
                        <a href="" @click.prevent='add(item.id)'>+</a>
                    </div>
                    <div class="del"  @click='del(item.id)'>x</div>
                </div>
            </div>

        `,
            methods: {
     
     
                changeNum: function (id, event) {
     
     
                    // console.log(id, event.target.value)
                    // 触发自定义事件
                    this.$emit('change-num', {
     
     
                        id: id,
                        num: event.target.value,
                        type: 'change'
                    })
                },
                sub: function (id) {
     
     
                    this.$emit('change-num', {
     
     
                        id: id,
                        type: 'sub'
                    })
                },
                add: function (id) {
     
     
                    this.$emit('change-num', {
     
     
                        id: id,
                        type: 'add'
                    })
                },
                del: function (id) {
     
     
                    // 把id传递给父组件
                    // console.log(id);
                    this.$emit('cart-del', id);
                }
            },
        }
        var CarTotal = {
     
     
            props: ['list'],
            template: `
            <div class="total">
                <span>总价:{
      
      {total}}</span>
                <button>结算</button>
            </div>
        `,
            // 添加第三属性
            computed: {
     
     
                total: function () {
     
     
                    // 计算商品的总价
                    var t = 0;
                    this.list.forEach((item) => {
     
     
                        t += item.price * item.num;
                    })
                    return t;
                }
            }
        }
        Vue.component('my-cart', {
     
     
            // 包含三个子属性  (局部属性)
            data: function () {
     
     
                return {
     
     
                    uname: '张三',
                    list: [
                        {
     
     
                            id: 1,
                            name: 'TCL彩电',
                            price: 1000,
                            num: 2,
                            img: 'img/a.jpg'
                        },
                        {
     
     
                            id: 2,
                            name: '机顶盒',
                            price: 2000,
                            num: 1,
                            img: 'img/b.jpg'
                        },
                        {
     
     
                            id: 3,
                            name: '海尔冰箱',
                            price: 1000,
                            num: 1,
                            img: 'img/c.jpg'
                        },
                        {
     
     
                            id: 4,
                            name: '小米手机',
                            price: 1000,
                            num: 1,
                            img: 'img/d.jpg'
                        },
                        {
     
     
                            id: 5,
                            name: '电视机',
                            price: 1000,
                            num: 1,
                            img: 'img/e.jpg'
                        }
                    ]
                }
            },
            template: `
            <div class="container">
                <cart-title :uname='uname'></cart-title>
                <cart-list :list='list' @change-num='changeNum($event)' @cart-del='delCart($event)'></cart-list>
                <cart-total :list='list'></cart-total>
            </div>
            `,
            components: {
     
     
                'cart-title': CarTitle,
                'cart-list': CarList,
                'cart-total': CarTotal,
            },
            methods: {
     
     
                changeNum: function (val) {
     
     
                    // 分为三种情况 : 输入域变更,加号变更,减号变更
                    if (val.type == 'change') {
     
     
                        // 根据子组件传递过来的数据,跟新list中对应的数据
                        this.list.some(item => {
     
     
                            if (item.id == val.id) {
     
     
                                item.num = val.num;
                                //     // 终止遍历
                                console.log(item.num)
                                return true;
                            }
                        })
                    } else if (val.type == 'sub') {
     
     
                        // 减一操作
                        this.list.some(item => {
     
     
                            if (item.id == val.id) {
     
     
                                item.num = 1;
                                //     // 终止遍历
                                return true;
                            }
                        })
                    } else if (val.type == 'add') {
     
     
                        // 加一操作
                        this.list.some(item => {
     
     
                            if (item.id == val.id) {
     
     
                                item.num += 1
                                //     // 终止遍历
                                return true;
                            }
                        })
                    }


                },
                delCart: function (id) {
     
     
                    // 根据id删除list中对应的数据
                    // 1.根据id 所对应数据的索引
                    var index = this.list.findIndex(item => {
     
     
                        return item.id == id;
                    });
                    // 2.根据索引删除对应的数据
                    this.list.splice(index, 1)
                }
            }
        })
        var vm = new Vue({
     
     
            el: '#app',
            data: {
     
     

            }
        })
    </script>

自我激励

人生没有笔直路,当你感到迷茫、失落时,找几部这种充满正能量的电影,坐下来静静欣赏,去发现生命中真正重要的东西。

猜你喜欢

转载自blog.csdn.net/weixin_50001396/article/details/112869192
今日推荐