2019-08-13 14:38:19  3584 0

vue实现购物车

 标签:   

vue实现购物车

大家好我是猪哥哥好久没更新博客了,今天用vue实现一个简单的购物车,效果图如下:


image.png

下面开始我们的舞台

由于业务代码太多,我们将 HTML、CSS、Javascript 分离为3个文件。便于小伙们查阅

  • index.html(引入资源及模版)

  • index.js(Vue实例及业务代码)

  • style.css (样式)

先在 index.html 中 引入 Vue.js以及相关资源,创建一个根元素来挂载 Vue实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车示例</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="app">
    
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="./index.js"></script>
</body>
</html>


var app = new Vue({
    el : '#app',
    data : {
        
    },
    methods: {
        
    },
    computed: {
        
    }
});

为了演示方便,我们需要的数据直接写在data里面,实际项目中应该通过Ajax从服务端动态获取的。

data : {
    list: [
        {
            id: 1,
            name: 'iPhone7',
            price: 6188,
            count: 1,
        },
        {
            id: 2,
            name: 'iPad Pro',
            price: 5888,
            count: 1,
        },
        {
            id: 3,
            name: 'MacBook Pro',
            price: 21488,
            count: 1,
        }
    ]
},

数据构建好后,可以在index.html中展示列表了,毫无疑问,肯定会用到循环 v-for 不过在此之前,我们先做一些小的优化,因为每个商品都是可以从购物车移除的,所以当列表为空时,在页面中显示一个“购物车为空” 的提示更为友好,我们可以通过判断数组list的长度来实现该功能:

<div id="app" v-cloak>
    <template v-if="list.length">
        
    </template>
    <div v-else>购物车为空</div>
</div>

<templete>里的代码主要分为两个部分,一个是商品的列表信息,我们可以用表格来展示,另一部分就是带有千位分割符的商品总价,(每隔三位数加一个逗号)。这部分代码如下:

<div id="app" v-cloak>
    <template v-if="list.length">
        <table>
            <thead>
            <tr>
                <th></th>
                <th>商品名称</th>
                <th>商品单价</th>
                <th>购买数量</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            
            </tbody>
        </table>
        <div>总价:¥ {{ totalPrice}}</div>
    </template>
    <div v-else>购物车为空1</div>
</div>

总价 totalPrice 是依赖商品的列表而动态改变的,所以我们可以使用计算属性来实现,这里有顺便讲解下分割符号要用到的知识点

我们罗列下 正则表达式符号需要用到的元字符:

1: \B 

元字符匹配非单词边界。匹配位置的上一个和下一个字符的类型是相同的:即必须同时是单词,或必须同时是非单词字符。字符串的开头和结尾处被视为非单词字符。

小例子:如图

image.png

如果未找到匹配,则返回 null。

2: (?=) 名词解释:?=n 量词匹配任何其后紧接指定字符串 n 的字符串。

用法:如图

image.png

这个例子比较难理解,就是查找all 前面出现的 指定字符 这里是 is

相信小伙伴们看到这里已经知道下面千位分割符需要用到的知识点了吧,我们继续开始我们的教程

我们需要用到的正则 核心: 

/\B(?=(\d{3})+$)/g

下面是代码:

computed: {
    totalPrice() {
        var total = 0;
        for(var i =0; i<this.list.length; i++) {
            var item  = this.list[i];
            total += item.price * item.count;
        }

        return total.toString().replace(/\B(?=(\d{3})+$)/g,',');
    }
}

最后就剩下商品列表渲染和相关的几个操作了。先在<tbody>内把数组list用v-for 指令循环出来

<tbody>
<tr v-for="(item,index) in list">
    <td>{{ index+1 }}</td>
    <td>{{ item.name }}</td>
    <td>{{ item.price }}</td>
    <td>
        <button @click="handleReduce(index)"
                :disabled="item.count === 1">-</button>
        {{ item.count }}
        <button @click="handleAdd(index)">+</button>
    </td>
    <td>
        <button @click="handleRemove(index)">移除</button>
    </td>
</tr>
</tbody>

最后奉上完整代码

index.html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车示例</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="app" v-cloak>
    <template v-if="list.length">
        <table>
            <thead>
            <tr>
                <th></th>
                <th>商品名称</th>
                <th>商品单价</th>
                <th>购买数量</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(item,index) in list">
                <td>{{ index+1 }}</td>
                <td>{{ item.name }}</td>
                <td>{{ item.price }}</td>
                <td>
                    <button @click="handleReduce(index)"
                            :disabled="item.count === 1">-</button>
                    {{ item.count }}
                    <button @click="handleAdd(index)">+</button>
                </td>
                <td>
                    <button @click="handleRemove(index)">移除</button>
                </td>
            </tr>
            </tbody>
        </table>
        <div>总价:¥ {{ totalPrice}}</div>
    </template>
    <div v-else>购物车为空</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="./index.js"></script>
</body>
</html>

index.js

var app = new Vue({
    el : '#app',
    data : {
        list: [
            {
                id: 1,
                name: 'iPhone7',
                price: 6188,
                count: 1,
            },
            {
                id: 2,
                name: 'iPad Pro',
                price: 5888,
                count: 1,
            },
            {
                id: 3,
                name: 'MacBook Pro',
                price: 21488,
                count: 1,
            }
        ]
    },
    methods: {
        handleReduce(index) {
            if (this.list[index].count ===1) return;
            this.list[index].count --;
        },
        handleAdd(index) {
            this.list[index].count++;
        },
        handleRemove(index) {
            this.list.splice(index,1);
        }
    },
    computed: {
        totalPrice() {
            var total = 0;
            for(var i =0; i<this.list.length; i++) {
                var item  = this.list[i];
                total += item.price * item.count;
            }

            return total.toString().replace(/\B(?=(\d{3})+$)/g,',');
        }
    }
});

style.css

[v-cloak] {
    display: none;
}
table {
    border: 1px solid #e9e9e9;
    border-collapse: collapse;
    border-spacing: 0;
    empty-cells: show;
}
th, td {
    padding: 8px 16px;
    border: 1px solid #e9e9e9;
    text-align: left;
}
th {
    background: #f7f7f7;
    color: #5c6b77;
    font-weight: 600;
    white-space: normal;
}

本次教程结束,有喜欢的朋友动动手指帮忙转发宣传,我们一起进步成长,期待下次更新