Vue mall shopping cart details processing optimization version: component development comprehensive case (detailed code analysis at the bottom)

demand:

Insert picture description here


Case show:Insert picture description here


Code display:

HTML part:

<!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>
<body>
    <div id="app">
        <div class="container">
            <my-cart></my-cart>
        </div>
    </div>
     <script src="./js/vue.js"></script>
     <script>
     //插入自己写的js
     </script>
</body>

css part: (In the future, write CSS styles to write hierarchical selectors as much as possible, and they have a heavy relationship

<style>
        .container {
            width: 100%;
            height: 100%;
        }
        
        .container .cart {
            width: 300px;
            margin: auto;
        }
        
        .container .title {
            background-color: lightblue;
            height: 40px;
            line-height: 40px;
            text-align: center;
        }
        
        .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: 0px;
            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 {
            user-select: none;
            /* 双击不选中 */
            position: absolute;
            top: 0px;
            right: 0px;
            width: 40px;
            text-align: center;
            font-size: 40px;
            cursor: pointer;
            color: red;
        }
        
        .container .item .del:hover {
            background-color: orange;
        }
    </style>

js part: (Key Analysis

    <script>
        //局部定义的变量组件一定要放在 全局component前面!!!! 
        var CartTitle = {
            props: ['uname'],
            template: `
            <div class="title">{{uname}}的购物车</div>
            `
        }
        var CartList = {
            props: ['lists'],
            template: `
            <div>
           <div class="item"  v-for="item in lists" :key="item.id">
           <img :src="item.img"/>
           <!-- 不能写成{{item.img}} 直接写item.img-->
           <div class="name">{{item.name}}</div>
           <div class="change">
           <a href="" @click.prevent='sub(item.id)'>&nbsp-&nbsp</a>
           <input name="" type="text" class="num" :value='item.num'  @blur='changeNum(item.id,$event)'></input>
           <a href="" @click.prevent='add(item.id)'>+&nbsp</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
                    })
                },
                //按+ -得到的数据也传递到changeNum
                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: ['lists'],
            template: `
          <div class="total">
          <span>总价:{{total}}</span>
          <button>结算</button>
          </div>
          `,
            computed: {
                //利用计算属性来计算总价  要有return值
                total: function() {
                    //计算商品总价
                    var sum = 0;
                    this.lists.forEach(item => {
                        //foeEach遍历出数据
                        sum += item.price * item.num;
                        //总价=单价x数量
                    })
                    return sum;
                }
            },
        }
        Vue.component('my-cart', {
            data() {
                return {
                    uname: 'XXW',
                    lists: [{
                        id: 1,
                        name: 'TCL彩电',
                        price: 1200,
                        num: 1,
                        img: 'img/a.jpg',
                    }, {
                        id: 2,
                        name: '机顶盒',
                        price: 800,
                        num: 1,
                        img: 'img/b.jpg',
                    }, {
                        id: 3,
                        name: '海尔冰箱',
                        price: 2200,
                        num: 1,
                        img: 'img/c.jpg',
                    }, {
                        id: 4,
                        name: '小米手机',
                        price: 1799,
                        num: 1,
                        img: 'img/d.jpg',
                    }, {
                        id: 5,
                        name: 'PPTV电视',
                        price: 1888,
                        num: 1,
                        img: 'img/e.jpg',
                    }, ]
                }
            },
            template: `
            <div class="cart">
                <cart-title :uname="uname"></cart-title>
                <cart-list :lists="lists" @change-num='changeNum($event)' @cart-del='delCart($event)'></cart-list>
                <cart-total :lists="lists"></cart-total>
                </div>
            
            `,
            components: {
                //第一局部组件 定义太多全局组件容易起冲突
                'cart-title': CartTitle,
                'cart-list': CartList,
                'cart-total': CartTotal
            },
            methods: {
                changeNum: function(val) {
                    var reg = /^[0-9]{1,5}$/; //正则匹配不能输入中文
                    //分三种情况:输入域变更,加号变更,减号变更
                    if (val.type == 'change') {
                        if (reg.test(val.num)) {
                            console.log(reg.test(val.num)); //true
                            console.log(typeof val.num); //隐式迭代 变成string型
                            //根据子组件传递过来的数据,跟新list中对应的数据
                            this.lists.some(item => {
                                if (item.id == val.id) {
                                    if (item.num > 0) {
                                        //输入框不能为负值
                                        item.num = val.num;
                                    } else {
                                        item.num = 0;
                                    }
                                    //终止遍历
                                    return true;
                                }
                            });
                        } else {
                            console.log(reg.test(val.num)); //false
                            this.lists.some(item => {
                                if (item.id == val.id) {
                                    item.num = 0;
                                    //终止遍历
                                    return true;
                                }
                            });
                        }
                    } else if (val.type == 'sub') {
                        //减一操作
                        this.lists.some(item => {
                            //不能减到0以下
                            if (item.id == val.id) {
                                if (item.num >= 1) {
                                    item.num = item.num * 1 - 1;
                                    //我的想法是给item.num*1 这样就又转number类型 直接把item.num 写成 item.Number(num)没有用 显示undefined
                                } else {
                                    item.num = 0;
                                }
                                //终止遍历
                                return true;
                            }

                        });
                    } else if (val.type == 'add') {
                        //加一操作
                        this.lists.some(item => {
                            if (item.id == val.id) {
                                item.num = item.num * 1 + 1;
                                //终止遍历
                                return true;
                            }
                        })
                    }
                },
                delCart: function(id) {
                    this.lists = this.lists.filter(function(item) { //把筛选后的结果重新赋值给books
                        return item.id != id //返回那些id 不相等的对象 形成一个新的数组
                    })
                }
            },
        });

        var vm = new Vue({
            el: '#app',
            data: {}
        })
    </script>

js code analysis:

1. Locally defined variable components must be placed in front of global components! ! !

2.<img :src="item.img"/>Cannot be written as {{item.img}}! ! Write item.img directly

3. Use computedcalculated attributes to have a return valuereturn

4. Use regular expression matching, so that the input box can only input numbers, it is directly zero in Chinese.

note! ! !: Num after regular expression matchingThe data type has changed (implicit iteration) number => string, Leading to the addition of the minus sign button is the addition of characters

Insert picture description here
Insert picture description here
Solution :

The code for the increase and decrease of the following addition and subtraction buttons is changed as follows

//加
item.num = item.num * 1 - 1;
//减
item.num = item.num * 1 + 1;

My idea is to give item.num * 1 in this way, then turn the number type directly to write item.num as item.Number (num) is useless and the result is undefined

5. (Detail handling) The operation of the minus key can't let him <0, use the condition to judge.

6.Two ways to write the delete button

The first one: (analysis see notes)

 delCart: function(id) {
                    this.lists = this.lists.filter(function(item) { //把筛选后的结果重新赋值给books
                        return item.id != id //返回那些id 不相等的对象 形成一个新的数组
                    })
                }

The second kind (analysis see notes)

 delCart: function(id) {
                    // 根据id删除list中对应的数据
                    // 1、找到id所对应数据的索引
                    var index = this.list.findIndex(item => {
                        return item.id == id;
                    });
                    // 2、根据索引删除对应数据
                    this.list.splice(index, 1);
                }
Published 28 original articles · praised 7 · visits 1178

Guess you like

Origin blog.csdn.net/haduwi/article/details/105282502