vue组件化实现购物车案例

这个案例主要是对组件化知识的应用,如何注册组件、父子组件间相互传递数据等有了一个实践。
案例一共分为三个组件,分别为标题组件、列表组件、结算组件。
首先是写一个静态页面,然后根据静态页面来进行组件化划分。
如下图所示:
在这里插入图片描述

  • 标题组件:通过父组件向子组件传递数据的方式,在父组件定义数据,然后将用户的动态名传递给子组件,在子组件中通过props属性来接收数据。

  • 列表组件:实现的功能主要有三个:
    ①渲染价格功能:也是通过父组件向子组件传递数据,将父组件中的list数据中的price渲染到列表中;
    ②删除商品功能:通过点击×号可以进行删除,通过自定义事件的方式将点击的id号传递给父组件,然后在父组件中将根据获得的id来进行删除,主要用到findIndex()方法来寻找索引,以及splice()方法来进行删除数组对象;
    ③修改商品数量功能:可以直接输入数量或者点击加减号来进行修改,首先是直接在表单中输入数量方式来进行修改,是通过自定义事件的方式将修改的商品的id和表单中的值传递给父组件,然后在父组件中根据id进行修改;点击加减号也是应用同样的方法,在子组件中自定义事件将id号传递给父组件,在父组件中进行加减商品数量;

  • 结算组件:定义一个计算属性total来进行计算所有商品的总价。

详细代码

(1)HTML结构:

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

(2)CSS样式结构:

 <style>
        * {
            padding: 0;
            margin: 0
        }
        
        a {
            text-decoration: none;
        }
        
        .container {
            width: 500px;
            margin: 10px auto;
        }
        
        .title {
            width: 500px;
            height: 50px;
            text-align: center;
            line-height: 50px;
            font-size: 20px;
            background-color: paleturquoise;
        }
        
        .item {
            position: relative;
            height: 50px;
            border-bottom: 1px solid paleturquoise;
        }
        
        .item img {
            float: left;
            width: 100px;
            height: 50px;
        }
        
        .item .price {
            position: absolute;
            float: left;
            width: 120px;
            margin-left: 10px;
            top: 15px;
            left: 100px;
        }
        
        .item .change {
            position: absolute;
            left: 220px;
            top: 15px;
            float: left;
            width: 200px;
        }
        
        .change a {
            float: left;
            display: block;
            width: 20px;
            height: 20px;
            font-size: 18px;
            text-align: center;
            line-height: 20px;
            background-color: #ccc;
        }
        
        .change input {
            float: left;
            width: 50px;
            margin: 0 5px;
        }
        
        .item .del {
            position: absolute;
            top: 8px;
            left: 420px;
            color: red;
            font-size: 24px;
        }
        
        .item .del:hover {
            top: 0;
            height: 50px;
            background-color: aquamarine;
        }
        
        .total {
            position: relative;
            width: 500px;
            height: 50px;
            background-color: sandybrown;
        }
        
        .total span {
            position: absolute;
            top: 14px;
            left: 250px;
        }
        
        .total span em {
            color: red;
            font-style: normal;
            font-size: 20px;
        }
        
        .total button {
            position: absolute;
            top: 8px;
            left: 400px;
            width: 50px;
            height: 35px;
            border-radius: 25%;
            border: none;
            outline: none;
            background-color: tomato;
        }
    </style>

(3)js代码结构:

<script src="js/vue.js"></script>
    <script>
        // 三个子组件
        var CartTitle = {
            props: ['uname'],
            template: `<div class="title">{{uname}}的商品</div>`
        }
        var CartList = {
            props: ['list'],
            template: ` <div class="list">
                    <div class="item" :key="item.id" v-for="item in list">
                        <img :src="item.img" alt="">
                        <div class="price">{{item.price}}¥/件</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: {
                // 向父组件传递需要删除的id
                del: function(id) {
                    // console.log(id);
                    this.$emit("del-cart", id);
                },
                // 修改表单输入的数量
                changenum: function(id, event) {
                    //console.log(id, event.target.value);
                    // 向父组件传递然后再修改数量
                    this.$emit('change-num', {
                        id: id,
                        num: event.target.value
                    })
                },
                // 点击减号按钮
                sub: function(id) {
                    this.$emit('sub-num', id);
                },
                //点击加号按钮
                add: function(id) {
                    this.$emit('add-num', id);
                }
            }
        }
        var CartTotal = {
                props: ['list'],
                template: `<div class="total">
                    <span>总价:<em>{{total}}</em>¥</span>
                    <button>结算</button>
                </div>`,
                computed: {
                    total: function() {
                        var sum = 0;
                        this.list.forEach(item => {
                            sum += item.price * item.num;
                        });
                        return sum;
                    }
                }
            }
            // 定义父组件
        Vue.component('my-cart', {
            data: function() {
                return {
                    uname: '蜗牛大哥',
                    list: [{
                        id: 1,
                        name: 'Nike鞋子',
                        price: 460,
                        num: 1,
                        img: 'images/nike.jpg'
                    }, {
                        id: 2,
                        name: 'TCL彩电',
                        price: 2800,
                        num: 1,
                        img: 'images/OIP.jpg'
                    }, {
                        id: 3,
                        name: 'iphone手机',
                        price: 5000,
                        num: 1,
                        img: 'images/phone.jpg'
                    }, {
                        id: 4,
                        name: 'vivo手机',
                        price: 3500,
                        num: 1,
                        img: 'images/vivo.jpg'
                    }]
                }
            },
            template: `<div class="mycart">
                <cart-title :uname="uname"></cart-title>
                <cart-list :list="list" @del-cart="delcart($event)" @change-num="changeNum($event)" @sub-num="subnum($event)" @add-num="addnum($event)"></cart-list>
                <cart-total :list="list"></cart-total>
                </div>`,
            components: {
                'cart-title': CartTitle,
                'cart-list': CartList,
                'cart-total': CartTotal,
            },
            methods: {
                delcart: function(id) {
                    // 根据id删除list中对应的数据
                    // 1.找到id对应数据的索引
                    var index = this.list.findIndex(item => {
                        return item.id == id;
                    });
                    // 2.根据索引删除对应的数据
                    this.list.splice(index, 1);
                },
                // 根据id修改list中的数量num
                changeNum: function(val) {
                    //console.log(val);
                    this.list.some(item => {
                        if (item.id == val.id) {
                            item.num = val.num;
                        }
                    })
                },
                //减号减少num
                subnum: function(event) {
                    // console.log(event); event是点击的id号
                    this.list.some(item => {
                        if (item.id == event && item.num > 0) {
                            item.num--;
                        }
                    })
                },
                // 加号增加num
                addnum: function(event) {
                    this.list.some(item => {
                        if (item.id == event) {
                            item.num++;
                        }
                    })
                }
            }
        });
        var vm = new Vue({
            el: "#app",
            data: {

            }
        });
    </script>

继续冲冲冲鸭~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值