需求:
购物车需要展示一个己加入购物车的商品列表,包含商品名称、商品单价、购买数量和操作
等信息,还需要实时显示购买的总价。还需要增加一个全选和选中该产品的功能,总价需要显示购选中的商品的总价。其中购买数量可以增加或减少,每类商品还可以从购物车中移除。
简易版
效果如下:
这里需要准备三个文件index.html, index.js,style.css
贴代码(这里用的语法糖 @ 代表 v-on)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="app" v-cloak>
<template v-if="list.length">
<table>
<thead>
<tr>
<th><input type="checkbox" v-model="all_checked" @click="chooseAll()"></th>
<th></th>
<th>商品名称</th>
<th>商品单价</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in list">
<td><input type="checkbox" @click="chooseCurrent(index)" v-model="item.checked"></td>
<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_format}}</div>
</template>
<div v-else>购物车为空</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js
var app = new Vue({
el: '#app',
data:{
list:[
{
id: 1,
name: 'iPhone 7',
price: 61888,
count: 100,
checked: false
},
{
id: 2,
name: 'iPad Pro',
price: 5888,
count: 1,
checked: false
},
{
id: 3,
name: 'MacBook Pro',
price: 21488,
count: 1,
checked: false
}
],
all_checked: false,
totalPrice: 0,
totalPrice_format: 0
},
methods: {
handleReduce: function (index) {
if(this.list[index].count === 1) return;
this.list[index].count --;
if( this.list[index].checked ) {
this.totalPrice -= this.list[index].price * 1;
this.totalPrice_format = this.totalPrice.toString().replace(/\B(?=(\d{3})+$)/g,',');
}
},
handleAdd: function (index) {
this.list[index].count ++;
this.totalPrice -= this.list[index].price * 1;
this.totalPrice_format = this.totalPrice.toString().replace(/\B(?=(\d{3})+$)/g,',');
if( this.list[index].checked ) {
this.totalPrice -= this.list[index].price * 1;
this.totalPrice_format = this.totalPrice.toString().replace(/\B(?=(\d{3})+$)/g,',');
}
},
handleRemove: function (index) {
if( this.list[index].checked ){
this.totalPrice -= this.list[index].count * this.list[index].price;
this.totalPrice_format = this.totalPrice.toString().replace(/\B(?=(\d{3})+$)/g,',');
}
this.list.splice(index,1);
},
chooseCurrent: function (index) {
var item = this.list[index];
item.checked = item.checked ? false : true;
if( item.checked ){
this.totalPrice += item.count * item.price;
var total_checked = true;
for( var i = 0; i < this.list.length; i++ ){
var item = this.list[i];
if( !item.checked ){
total_checked = false;
break;
}
}
if( total_checked ){
this.all_checked = true;
}else{
this.all_checked = false;
}
}else{
this.totalPrice -= item.count * item.price;
this.all_checked = false;
}
this.totalPrice_format = total.toString().replace(/\B(?=(\d{3})+$)/g,',');
},
chooseAll: function () {
this.all_checked = this.all_checked ? false : true;
this.totalPrice = 0;
if( this.all_checked ){
for( var i = 0; i < this.list.length; i++ ){
var item = this.list[i];
this.totalPrice += item.price * item.count;
item.checked = true;
}
}else{
for( var i = 0; i < this.list.length; i++ ){
var item = this.list[i];
item.checked = false;
}
}
this.totalPrice_format = this.totalPrice.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: nowrap;
}
遍历二维数组
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="app" v-cloak>
<template v-if="list.length">
<table>
<thead>
<tr>
<th><input type="checkbox" v-model="all_checked" @click="chooseAll()"></th>
<th>商品ID</th>
<th>商品名称</th>
<th>商品单价</th>
<th>购买数量</th>
<th>商品类别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<template v-for="(parent,index) in list">
<tr v-for="(child,childindex) in parent">
<td><input type="checkbox" @click="chooseCurrent(index,childindex)" v-model="child.checked"></td>
<td>{{ child.id }}</td>
<td>{{ child.name }}</td>
<td>{{ child.price }}</td>
<td>
<button @click="handleReduce(index,childindex)" :disabled="child.count === 1">-</button>
{{ child.count }}
<button @click="handleAdd(index,childindex)">+</button>
</td>
<td>{{ child.category }}</td>
<td>
<button @click="handleRemove(index,childindex)">移除</button>
</td>
</tr>
</template>
</tbody>
</table>
<div>总价:¥ {{ totalPrice }}</div>
</template>
<div v-else>购物车为空</div>
</div>
<script src="../../Vue/vue.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js
var app = new Vue({
el: '#app',
data:{
list:[
[
{
id: 1,
name: 'iPhone 7',
price: 61888,
count: 100,
checked: false,
category: '电子商品'
},
{
id: 2,
name: 'iPad Pro',
price: 5888,
count: 1,
checked: false,
category: '电子商品'
},
{
id: 3,
name: 'MacBook Pro',
price: 21488,
count: 1,
checked: false,
category: '电子商品'
}
],
[
{
id: 4,
name: '毛巾',
price: 10.9,
count: 100,
checked: false,
category: '生活用品'
},
{
id: 5,
name: '纸巾',
price: 29.99,
count: 10,
checked: false,
category: '生活用品'
},
{
id: 6,
name: '地毯',
price: 299.99,
count: 1,
checked: false,
category: '生活用品'
}
],
[
{
id: 7,
name: '苹果',
price: 10.9,
count: 100,
checked: false,
category: '果蔬'
},
{
id: 8,
name: '美国进口橙子',
price: 15,
count: 10,
checked: false,
category: '果蔬'
},
{
id: 9,
name: '智利进口樱桃',
price: 59.9,
count: 1,
checked: false,
category: '果蔬'
}
]
],
all_checked: false,
totalPrice: 0,
totalPrice_format: 0
},
methods: {
handleReduce: function (index,childindex) {
if(this.list[index][childindex].count === 1) return;
this.list[index][childindex].count --;
console.log(this.list[index][childindex].price);
if( this.list[index][childindex].checked ){
this.totalPrice -= this.list[index][childindex].price;
this.totalPrice_format = this.totalPrice.toFixed(2).toString().replace(/\B(?=(\d{3})+$)/g,',');
}
},
handleAdd: function (index,childindex) {
this.list[index][childindex].count ++;
if( this.list[index][childindex].checked ){
console.log(this.totalPrice);
this.totalPrice += this.list[index][childindex].price;
this.totalPrice_format = this.totalPrice.toFixed(2).toString().replace(/\B(?=(\d{3})+$)/g,',');
}
},
handleRemove: function (index,childindex) {
if( this.list[index][childindex].checked ){
this.totalPrice -= this.list[index][childindex].count * this.list[index][childindex].price;
}
this.list[index].splice(childindex,1);
this.totalPrice_format = this.totalPrice.toFixed(2).toString().replace(/\B(?=(\d{3})+$)/g,',');
},
chooseCurrent: function (index,childindex) {
var item = this.list[index][childindex];
item.checked = item.checked ? false : true;
if( item.checked ){
this.totalPrice += item.count * item.price;
var total_checked = true;
for( var i = 0; i < this.list.length; i++ ){
var v = this.list[i];
for( var j = 0; j < v.length; j++ ){
var product = v[j];
if( !product.checked ){
total_checked = false;
break;
}
}
}
if( total_checked ){
this.all_checked = true;
}else{
this.all_checked = false;
}
}else{
this.totalPrice -= item.count * item.price;
this.all_checked = false;
}
this.totalPrice_format = this.totalPrice.toFixed(2).toString().replace(/\B(?=(\d{3})+$)/g,',');
},
chooseAll: function () {
this.all_checked = this.all_checked ? false : true;
this.totalPrice = 0;
if( this.all_checked ){
for( var i = 0; i < this.list.length; i++ ){
var v = this.list[i];
for( var j = 0; j < v.length; j++ ){
var item = v[j];
this.totalPrice += item.price * item.count;
item.checked = true;
}
}
}else{
for( var i = 0; i < this.list.length; i++ ){
var v = this.list[i];
for( var j = 0; j < v.length; j++ ){
var item = v[j];
item.checked = false;
}
}
}
this.totalPrice_format = this.totalPrice.toFixed(2).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: nowrap;
}