1. 介绍
这是一个Vue实例,实现一个简单的购物车功能。用于实践Vue的数据绑定,条件,循环,父子通信等功能。
2. 代码实现步骤
2.1 初始界面显示
<body>
<div id="a_div">
<table style="width: 99%;" border="2px">
<tr>
<th>
<label for="quan">
<!-- 这里的 $event 是将当前对象传入进去,具体详情请参照vue官方文档 -->
<input id="quan" type="checkbox" > 全选
</label>
</th>
<th>商品名称</th>
<th>商品价格</th>
<th>购买数量</th>
<th>小计</th>
<th>操作</th>
</tr>
<tr v-for="item,index in data1">
<td style="text-align: center;">
<input type="checkbox" >
</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><input type="text" v-model="item.sum" /></td>
<td>{{item.price*item.sum}}</td>
<td>
<button type="button" v-on:click="remove(item.name)">删除</button>
</td>
</tr>
</table>
<div v-if="">
共{{ count }}件商品 购物车总金额:¥{{total}}元
</div>
</div>
</body>
数组定义
<script type="text/javascript">
new Vue({
el: '#a_div',
data: {
data1: [{
name: '玻璃珠',
price: 19.9,
sum: 5,
value: 'bolizhu'
}, {
name: '三国演义',
price: 39.9,
sum: 10,
value: 'sanguoyanyi'
}, {
name: '红楼梦',
price: 48.8,
sum: 15,
value: 'hongloumeng'
}],
checkData: [] // 双向数据绑定的数组
}
</script>
显示结果
2.2 删除功能
在上述代码块中删除按钮做了个点击事件进行删除,传输当前对象名称
v-on:click=“remove(item.name)”
methods: {
//删除
remove: function(item) {
//获取到传输的名称
var name = item;
this.data1.splice(this.data1.indexOf(name), 1);
}
}
补充小计
直接在上述代码计算即可
直接将当前对象的价格*上数量即可
结果测试
2.3 全选反选
这里有两种方法进行全选反选,当然这也是难点因为要跟后续选中计算总金额挂钩
第一种
通过watch 监视双向绑定的数组变化
点击全选按钮通过click方法将当前对象传入进去,在通过方法判断进行选中
计算的是全部商品的数量与总价格
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>购物车</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="a_div">
<table style="width: 99%;" border="2px">
<tr>
<th>
<label for="quan">
<!-- 这里的 $event 是将当前对象传入进去,具体详情请参照vue官方文档 -->
<input id="quan" type="checkbox" @click="checkAll($event)" > 全选
</label>
</th>
<th>商品名称</th>
<th>商品价格</th>
<th>购买数量</th>
<th>小计</th>
<th>操作</th>
</tr>
<tr v-for="item,index in data1">
<td style="text-align: center;">
<!-- v-model 双向数据绑定命令 -->
<input class="checkItem" type="checkbox" :value="item.value" v-model="checkData">
</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><input type="text" v-model="item.sum" /></td>
<td>{{item.price*item.sum}}</td>
<td>
<button type="button" v-on:click="remove(item.name)">删除</button>
</td>
</tr>
</table>
<div v-if="">
共{{ count }}件商品 购物车总金额:¥{{total}}元
</div>
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#a_div',
data: {
data1: [{
name: '玻璃珠',
price: 19.9,
sum: 5,
value: 'bolizhu'
}, {
name: '三国演义',
price: 39.9,
sum: 10,
value: 'sanguoyanyi'
}, {
name: '红楼梦',
price: 48.8,
sum: 15,
value: 'hongloumeng'
}],
checkData: [] // 双向数据绑定的数组
},
watch: {
checkData: { // 监视双向绑定的数组变化
handler() {
if (this.checkData.length == this.data1.length) {
document.querySelector('#quan').checked = true;
} else {
document.querySelector('#quan').checked = false;
}
},
deep: true
}
},
//双向数据绑定计算属性
computed: {
//共多少件商品
count: function() {
var num = 0;
for (var i in this.data1) {
num += parseInt(this.data1[i].sum);
}
return num;
},
//商品总价值
total: function() {
var total = 0;
for (var i in this.data1) {
total += this.data1[i].price * this.data1[i].sum;
}
return total;
}
},
methods: {
//删除
remove: function(item) {
//获取到传输的名称
var name = item;
this.data1.splice(this.data1.indexOf(name), 1);
},
checkAll(e) { // 点击全选事件
if (e.target.checked) {
this.data1.forEach((el, i) => {
// 数组里没有这一个value才push,防止重复push
if (this.checkData.indexOf(el.value) == '-1') {
this.checkData.push(el.value);
}
});
} else { // 全不选选则清空绑定的数组
this.checkData = [];
}
}
}
})
</script>
</html>
结果显示
结果可能并不明显,可以复制代码进行测试。
第二种与全选计算总价挂钩
get默认调用
computed监测的值变化的时候,set会被调用
every()判断数组中是否每个元素都满足条件只有都满足条件才返回true。只要有一个不满足就返回false;
reduce()数组方法 reduce 用来迭代一个数组,并且把它累积到一个值中
prev:上一次回调的处理结果
next:对应的是数组本身
总代码块
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>购物车</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="a_div">
<table style="width: 99%;" border="2px">
<tr>
<th>
<input id="quan" type="checkbox" v-model="checkboxAll"> 全选
</th>
<th>商品名称</th>
<th>商品价格</th>
<th>购买数量</th>
<th>小计</th>
<th>操作</th>
</tr>
<tr v-for="item,index in data1">
<td style="text-align: center;">
<!-- v-model 双向数据绑定命令 -->
<input class="checkItem" type="checkbox" :value="item.value" v-model="item.isSelected">
</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><input type="text" v-model="item.sum" /></td>
<td>{{item.price*item.sum}}</td>
<td>
<button type="button" v-on:click="remove(item.name)">删除</button>
</td>
</tr>
</table>
购物车总计{{ count }}件商品 (无需选中)<br />
选中商品总金额:¥{{sum}}元
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#a_div',
data: {
data1: [{
name: '玻璃珠',
price: 19.9,
sum: 5,
isSelected: false
}, {
name: '三国演义',
price: 39.9,
sum: 10,
isSelected: false
}, {
name: '红楼梦',
price: 48.8,
sum: 15,
isSelected: false
}],
checkData: [] // 双向数据绑定的数组
},
//双向数据绑定计算属性
computed: {
//共多少件商品
count: function() {
var num = 0;
for (var i in this.data1) {
num += parseInt(this.data1[i].sum);
}
return num;
},
checkboxAll: {
get: function() {
return this.data1.every(d => d.isSelected);
},
set: function(val) {
//val属于boolean值,相当于是否选中
this.data1.forEach(d => d.isSelected = val);
}
},
//求总价
sum: {
get() {
return this.data1.reduce((prev, next) => {
if (!next.isSelected) {
//当前对象取消选中就返回上一次选中的值
return prev;
}
//上一次选中的值加....
return prev + next.price * next.sum;
}, 0)
}
}
},
methods: {
//删除
remove: function(item) {
//获取到传输的名称
var name = item;
this.data1.splice(this.data1.indexOf(name), 1);
}
}
})
</script>
</html>
测试结果
3. 总结
- 理清思路
- 了解方法用途