• 案例:购物车功能


    静态页面的样式如下:

    静态页面模板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <style type="text/css">
        .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;
        }
    </style>
    
    <body>
        <div id="app">
            <div class="container">
                <div class="cart">
                    <div class="title">我的商品</div>
                    <div>
                        <div class="item">
                            <img src="img/a.jpg" />
                            <div class="name"></div>
                            <div class="change">
                                <a href=""></a>
                                <input type="text" class="num" />
                                <a href=""></a>
                            </div>
                            <div class="del">×</div>
                        </div>
                        <div class="item">
                            <img src="img/b.jpg" />
                            <div class="name"></div>
                            <div class="change">
                                <a href=""></a>
                                <input type="text" class="num" />
                                <a href=""></a>
                            </div>
                            <div class="del">×</div>
                        </div>
                        <div class="item">
                            <img src="img/c.jpg" />
                            <div class="name"></div>
                            <div class="change">
                                <a href=""></a>
                                <input type="text" class="num" />
                                <a href=""></a>
                            </div>
                            <div class="del">×</div>
                        </div>
                        <div class="item">
                            <img src="img/d.jpg" />
                            <div class="name"></div>
                            <div class="change">
                                <a href=""></a>
                                <input type="text" class="num" />
                                <a href=""></a>
                            </div>
                            <div class="del">×</div>
                        </div>
                        <div class="item">
                            <img src="img/e.jpg" />
                            <div class="name"></div>
                            <div class="change">
                                <a href=""></a>
                                <input type="text" class="num" />
                                <a href=""></a>
                            </div>
                            <div class="del">×</div>
                        </div>
                    </div>
                    <div class="total">
                        <span>总价:123</span>
                        <button>结算</button>
                    </div>
                </div>
            </div>
        </div>
        <script type="text/javascript" src="js/vue.js"></script>
        <script type="text/javascript">
            var vm = new Vue({
                el: '#app',
                data: {
    
                }
            });
        </script>
    </body>
    </html>

    重构为vue模板后:

    需求分析 :

    1. 按照组件化方式实现业务需求

    • 根据业务功能进行组件化划分

    ① 标题组件(展示文本)

    ② 列表组件(列表展示、商品数量变更、商品删除)

    ③ 结算组件(计算商品总额)

    2. 功能实现步骤

    • 实现整体布局和样式效果
    • 划分独立的功能组件
    • 组合所有的子组件形成整体结构
    • 逐个实现各个组件功能
      • 标题组件
      • 列表组件
      • 结算组件
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <style type="text/css">
        .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;
        }
    </style>
    
    <body>
        <div id="app">
            <div class="container">
                <my-cart></my-cart>
            </div>
        </div>
        <script type="text/javascript" src="js/vue.js"></script>
        <script type="text/javascript">
            var CartTitle = {
                props: ['uname'],
                template: `
            <div class="title">{{uname}}的商品</div>
          `
            }
            var CartList = {
                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)'>×</div>
              </div>
            </div>
          `,
                methods: {
                    // 下面的所有方法都是要将数据传递给父组件,然后在父组件中处理
                    changeNum: function (id, event) {
                        this.$emit('change-num', {
                            id: id,
                            type: 'change',
                            num: event.target.value
                        });
                    },
                    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传递给父组件
                        this.$emit('cart-del', id);
                    }
                }
            }
            var CartTotal = {
                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: 1,
                            img: 'img/a.jpg'
                        }, {
                            id: 2,
                            name: '机顶盒',
                            price: 1000,
                            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: 'PPTV电视',
                            price: 1000,
                            num: 2,
                            img: 'img/e.jpg'
                        }]
                    }
                },
                template: `
            <div class='cart'>
              <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': CartTitle,
                    'cart-list': CartList,
                    'cart-total': CartTotal
                },
                methods: {
                    changeNum: function (val) {
                        // 分为三种情况:输入域变更、加号变更、减号变更
                        if (val.type == 'change') {
                            // 根据子组件传递过来的数据,跟新list中对应的数据
                            this.list.some(item => {
                                if (item.id == val.id) {
                                    item.num = val.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>
    </body>
    </html>

    注意:

    ① 修改文本框数量操作和删除操作等操作都应该在父组件中进行处理,因为不推荐在子组件中直接操作props中的数据,而应该通知父组件去处理。+1和-1的操作也不能在子组件中完成,必须要在父组件中处理。

    不能使用v-model来绑定数量的文本框,因为v-model绑定的数据是双向的,而我们在子组件中不能改变props中的数据。所以我们直接把数量显示出来即可

    <input type="text" class="num" :value='item.num' @blur='changeNum(item.id, $event)'/>

    那什么时候修改这个值呢?需要我们手动去绑定对应的事件。用blur事件,失去焦点的时候更新文本框里面的数量。这个处理也不是在子组件中完成的,而是在父组件中进行处理。

    ③ some方法的规则:终止遍历使用的是return true。

    尚未解决的问题:持续点击减号按钮,会出现负值

  • 相关阅读:
    NLP(五)
    pyinstaller+wxpython+selinum
    C++ 动态库和静态库
    谷粒商城(三) 部署
    Centos使用KVM创建虚拟机
    C++指针
    C++异常处理
    C++流类库与输入/输出
    C++泛型程序设计及STL的结构
    selenium java maven testNg环境搭建
  • 原文地址:https://www.cnblogs.com/zcy9838/p/13156222.html
Copyright © 2020-2023  润新知