vue购物车案例
目标:实现一个购物车如下。
html如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍购物车</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">
<div v-if="list.length">
<table>
<!--头部属性那一行-->
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<!--书籍内容部分-->
<tbody>
<!--同时获取对象和下标,v-if如果数量小于1为假的,直接删除该图书-->
<tr v-for="(book,index) in list" v-if="book.count">
<th>{{book.id}}</th>
<th>{{book.name}}</th>
<th>{{book.date}}</th>
<th>{{book.price | showPrice}}</th>
<th>
<button @click="add(book)">+</button>
{{book.count}}
<!--绑定一个disabled,当数量小于等于1时无法点击减号按钮。其实多此一举只是为了直到有该用法-->
<button @click="sub1(book,index)" :disabled="book.count<=1">-</button>
</th>
<th>
<button @click="remove(index)">移除</button>
</th>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="5">总价格:{{totalPrice|showPrice}}</th>
</tr>
</tfoot>
</table>
</div>
<span v-else>您懂得购物车已清空</span>
</div>
<script src="../../js/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
CSS如下
* {
margin: 0;
padding: 0
}
#app table {
margin: 100px 350px;
width: 600px;
height: 250px;
background-color: #ccc;
display: inline-block;
font-size: 15px;
}
/*设置每个标题的宽度*/
#app table thead th:nth-child(1) {
width: 50px;
height: 50px;
}
#app table thead th:nth-child(2) {
width: 150px;
height: 50px;
}
#app table thead th:nth-child(3) {
width: 100px;
height: 50px;
}
#app table thead th:nth-child(4) {
width: 100px;
height: 50px;
}
#app table thead th:nth-child(5) {
width: 100px;
height: 50px;
}
/*设置按钮的大小*/
#app table tbody th>button {
width: 40px;
height: 30px;
background-color: #CCCCCC;
}
/*设置购物车清空界面*/
span {
width: 250px;
height: 50px;
display: inline-block;
position: absolute;
left: 400px;
top: 150px;
font-size: 25px;
font-family: '宋体';
font-style: italic;
font-weight: 900;
line-height: 50px;
text-align: center;
}
JS如下
const app = new Vue({
el: '#app',
data: {
list: [
{
id: 1,
name: '《算法导论》',
date: '2006-9',
price: 85.00,
count: 1
},
{
id: 2,
name: '《UNIX编程艺术》',
date: '2006-2',
price: 59.00,
count: 1
},
{
id: 3,
name: '《编程珠玑》',
date: '2008-10',
price: 39.00,
count: 1
},
{
id: 4,
name: '《代码大全》',
date: '2006-3',
price: 128.00,
count: 1
},
],
allMoney: 311,
},
methods: {
//绑定单击事件同时传入该书籍对象,进行修改
add(book) {
book.count++;
/*总价加一*/
// this.allMoney = this.allMoney + book.price;
},
sub1(book, index) {
book.count--;
/*总价减一*/
// this.allMoney = this.allMoney - book.price;
},
remove(index) {
this.list.splice(index, 1);
}
},
/*计算属性还可以通过计算属性专门来处理*/
computed: {
totalPrice() {
let totalPrice = 0;//保存计算的总价格
for (let i = 0; i < this.list.length; i++) {
totalPrice += this.list[i].count*this.list[i].price;
}
return totalPrice;
}
},
/*过滤器:会自动将|前的变量当成参数传入后边的函数中*/
filters: {
showPrice(price) {
return '¥' + price.toFixed(2);
}
},
});
总结
1.如果不采用vue,我们的html代码中表格的内容部分将会十分繁琐,每一个样品都会添加一行信息,但是他们html格式是重复的,采用v-for遍历商品数组,动态创建每个商品的的tr.
2.在获取商品数组时,我获取了每个商品对象和其下标,后边我都是操作每个对象的,视频中老师是通过index再去通过下标访问数组,我觉得太麻烦了,既然我们已经获取到每个对象,就直接使用。
3.在增加和减少按钮部分,我直接计算了总价格,既然有计算属性,那么还是交给计算属性computed来实现吧,后来改了。
4.在减少按钮部分我直接进行判断,一旦数量小于等于0直接不显示该行信息,但是这和移除按钮功能其实冲突了,我是直接采用v-if来实现,其取值我直接取book.count,很简便,只要数量为0时,直接不显示该行,我同时将商品信息数组删除该商品,如果长度为0,直接改表格不显示。
5.所有的商品信息移除后,就显示购物车为空,他们其实是互斥关系,可以使用v-if/else.
6.过滤器学会了格式化数据样式,还有toFixed()函数,括号里的参数就是保留的位数。
过滤器问题
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
过滤器可以串联:
{{ message | filterA | filterB }}
在这个例子中,filterA
被定义为接收单个参数的过滤器函数,表达式 message
的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB
,将 filterA
的结果传递到 filterB
中。
局部过滤器要添加s
/*过滤器:会自动将|前的变量当成参数传入后边的函数中*/
filters: {
showPrice(price) {
return '¥' + price.toFixed(2);
}
},
如果不小心没有写s就会产生下边的报错
[Vue warn]: Failed to resolve filter: showPrice
全局的过滤器不用加s,
但是要定义在new Vue上边。