简单版购物车实例
本节通过购物车实例巩固 v-for 循环遍历数据、v-model 数据双向绑定、数据定义、方法定义、v-if 等知识点。
购物车实例简介
由于还没有介绍网络数据请求,本节采用模拟数据进行购物车讲解,在此实例中将会讲解购物车数量计算、价格计算、购物车多选和全选等操作,最终效果如图 2-1 所示。

静态页面布局
下列代码只包括视图层代码和 M 层代码,样式代码可在配套资源中下载。 |
视图层代码如下。
<div id="app">
<div class="head">购物车</div>
<table cellpadding="5" cellspacing="0">
<tr>
<td><input type="checkbox" /></td>
<td><img src="p1.jpg" /></td>
<td>五香瓜子<span>19</span></td>
<td>
<button>-</button>
<input type="text" value="1" />
<button>+</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td><img src="p1.jpg" /></td>
<td>五香瓜子<span>19</span></td>
<td>
<button>-</button>
<input type="text" value="1" />
<button>+</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td><img src="p1.jpg" /></td>
<td>五香瓜子<span>19</span></td>
<td>
<button>-</button>
<input type="text" value="1" />
<button>+</button>
<button>删除</button>
</td>
</tr>
</table>
<div class="footer">
<input type="checkbox" />全选
<i>总数量:100</i>
<i>总价:1000</i>
</div>
</div>
Vue 初始代码如下。
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'hello'
}
});
</script>
渲染购物车列表
(1)在 data 中模拟购物车数据,代码如下。
<script>
var vm = new Vue({
el: '#app',
data: {
// 模拟购物车数据
cartlist: [
{
id: 1,
imgurl: 'https://i.loli.net/2021/04/29/YqZCykhzotGmx6D.jpg',
title: '瓜子',
price: 30,
num: 1,
check: false // 记录是否选中
},
{
id: 2,
imgurl: 'https://i.loli.net/2021/04/29/dHNmEWJgCajtMr1.jpg',
title: '花生',
price: 30,
num: 1,
check: false
},
{
id: 3,
imgurl: 'https://i.loli.net/2021/04/29/12CdfSPayn5QOb6.jpg',
title: '西瓜子',
price: 30,
num: 2,
check: false
}
]
}
});
</script>
代码解析如下。
对象中的 check 表示是否选中该商品,false 表示未选中,true 表示已选中。
(2)将 data 中定义的购物车数据渲染到视图层,代码如下。
<table cellpadding="5" cellspacing="0">
<tr v-for="(item, i) in cartlist" :key="i">
<td v-if="item.check">
<input type="checkbox" checked />
</td>
<td v-else>
<input type="checkbox" />
</td>
<td>
<img :src="item.imgurl" />
</td>
<td>
{{ item.title }}<span>{{ item.price }}</span>
</td>
<td>
<button>-</button>
<input type="text" :value="item.num" />
<button>+</button>
</td>
</tr>
</table>
代码解析如下。
使用 v-if 和 v-else 控制 checkbox 选中状态,当 v-if 结果为 true 时,checkbox 为选中状态。
修改商品选中状态
前述实例只是把商品渲染完成,并根据 check 属性值显示商品是否被选中。但是当选中 checkbox 复选框时,并不能实时修改 check 属性值,本节将实现商品选中状态的实时修改。
在视图层给 checkbox 添加单击事件,代码如下。
<tr v-for="(item, i) in cartlist" :key="i">
<td v-if="item.check">
<input type="checkbox" checked @click="checkbtn(i)" />
</td>
<td v-else>
<input type="checkbox" @click="checkbtn(i)" />
</td>
</tr>
代码解析如下。
checkbtn(i) 为事件方法,需要传递数组索引作为参数,其目的是记录具体操作的是哪一种商品。
在 methods 中定义 checkbtn 方法,代码如下。
methods: {
// 单击 checkbox 修改 check 值
checkbtn(i) {
// 打印选中商品
console.log(this.cartlist[i]);
// 修改 check 属性
this.cartlist[i].check = !this.cartlist[i].check;
}
}
记录选中商品的总数量和总价格
当前我们已经实现了商品选中和取消状态的实时操作,本节实现选中商品的总数量和总价格功能。
(1)在 data 中定义 allPrice 和 allNum 属性,记录商品的总数量和总价格,代码如下。
data() {
return {
allPrice: 0, // 总价格
allNum: 0, // 总数量
// 模拟购物车数据
cartlist: [
// ...
]
};
}
(2)在视图层渲染商品的总数量和总价格,代码如下。
<div class="footer">
<input type="checkbox" />全选
<i>总数量:{{ allNum }}</i>
<i>总价格:{{ allPrice }}</i>
</div>
(3)在 methods 中定义 getAllNum() 方法,获取商品总数量
methods: {
// 获取商品总数量
getAllNum() {
var num = 0;
for (var i = 0; i < this.cartlist.length; i++) {
if (this.cartlist[i].check == true) {
// 选中商品的数量(可能买多个)
num += parseInt(this.cartlist[i].num);
}
}
this.allNum = num;
}
}
(4)在 checkbtn() 方法中调用 getAllNum() 方法
methods: {
checkbtn(i) {
console.log(this.cartlist[i]);
this.cartlist[i].check = !this.cartlist[i].check;
// 获取总数量
this.getAllNum();
}
}
(5)在 methods 中定义 getAllPrice() 方法,获取商品总价格
methods: {
// 获取总价格
getAllPrice() {
var num = 0;
for (var i = 0; i < this.cartlist.length; i++) {
if (this.cartlist[i].check == true) {
num += parseInt(this.cartlist[i].num) * this.cartlist[i].price;
}
}
this.allPrice = num;
}
}
代码解析如下。
循环遍历整个商品列表,当商品中的 check 属性为 true 时,表示选中了该商品,商品总价格为选中商品的数量×选中商品的价格,最后把遍历出来的商品总价赋值给 data 中的 allPrice。
(6)在 checkbtn() 方法中调用 getAllPrice() 方法,代码如下。
methods: {
checkbtn(i) {
console.log(this.cartlist[i]);
this.cartlist[i].check = !this.cartlist[i].check;
// 获取总数量
this.getAllNum();
// 获取总价格
this.getAllPrice();
},
}
全选状态
全选分为两种状态,即状态1:选中所有商品。当把所有的商品都选中时,最底部的 “全选” 复选框应该自动选中。状态2:选中底部的 “全选” 复选框。当选中最底部的 “全选” 复选框时,列表中所有的商品应该都被选中。
状态1:选中所有商品
(1)在 data 属性中,新增选中 allCheck 记录的总条数,如果选中的总条数等于商品列表的条数,表示选中了所有商品,代码如下。
data() {
return {
allCheck: 0, // 选中总条数
allPrice: 0, // 总价格
allNum: 0, // 总数量
cartlist: [ // 购物车商品列表
// ...
]
};
}
(2)在 methods 中新增 getAllCheck() 方法,获取选中商品的个数,代码如下。
methods: {
// 判断全选,获取选中个数
getAllCheck() {
var num = 0;
for (var i = 0; i < this.cartlist.length; i++) {
if (this.cartlist[i].check == true) {
num++;
}
}
this.allCheck = num;
}
}
(3)在 checkbtn() 方法中调用 getAllCheck() 方法
methods: {
checkbtn(i) {
console.log(this.cartlist[i]);
this.cartlist[i].check = !this.cartlist[i].check;
// 获取总数量
this.getAllNum();
// 获取总价格
this.getAllPrice();
// 获取选中个数
this.getAllCheck();
}
}
(4)使用 v-if 判断底部的全选按钮是否被选中,代码如下。
<div class="footer">
<em v-if="allCheck == cartlist.length">
<input type="checkbox" checked />全选
</em>
<em v-else>
<input type="checkbox" />全选
</em>
</div>
状态2:选中底部的“全选”复选框
(1)在视图层给 “全选” 复选框增加 allCheckbtn 单击事件,代码如下。
<div class="footer">
<em v-if="allCheck == cartlist.length">
<input type="checkbox" checked @click="allCheckbtn" />全选
</em>
<em v-else>
<input type="checkbox" @click="allCheckbtn" />全选
</em>
<i>总数量:{{ allNum }}</i>
<i>总价:{{ allPrice }}</i>
</div>
(2)在 methods 中新增 allCheckbtn() 方法,实现全选功能,并计算商品数量和商品价格,代码如下。
methods: {
allCheckbtn(e) {
// 判断“全选”复选框是否选中
console.log(e.target.checked);
if (e.target.checked) {
// 如果选中,将所有商品的 check 属性设置为 true
for (var i = 0; i < this.cartlist.length; i++) {
this.cartlist[i].check = true;
}
} else {
// 如果未选中,将所有商品的 check 属性设置为 false
for (var i = 0; i < this.cartlist.length; i++) {
this.cartlist[i].check = false;
}
}
// 获取总数量
this.getAllNum();
// 获取总价格
this.getAllPrice();
}
}
代码解析如下。
为 allCheckbtn() 方法添加事件参数 e,“e.target.checked” 可以判断复选框是 true 还是 false,true 表示选中 “全选” 复选框,false 表示未选中 “全选” 复选框。
如果是选中状态,循环遍历整个商品列表,拿到每件商品的 check 属性,设置为选中状态 true,同时调用计算商品总数量和总价格的方法即可。
商品数量增加或减少
购物车的最后一个功能是商品数量的增加或减少,具体实现步骤如下。
(1)在视图层为 “增加” 和 “减少” 按钮处添加单击事件,并传入商品索引,表示具体操作哪条数据。
<button @click="min(i)">-</button>
<input type="text" :value="item.num" />
<button @click="add(i)">+</button>
(2)在 methods 中新增 add() 和 min() 方法
methods: {
// 增加商品数量
add(i) {
this.cartlist[i].num++;
// 获取总数量
this.getAllNum();
// 获取总价格
this.getAllPrice();
},
// 减少商品数量
min(i) {
// 如果商品数量已经是 1,则不再减少
if (this.cartlist[i].num == 1) {
return;
}
this.cartlist[i].num--;
// 获取总数量
this.getAllNum();
// 获取总价格
this.getAllPrice();
}
}