1.需求讲解
我们不仅要实现上面的页面,还要实现以下功能:
- 实现购买数量的增减,且数量为1时
-
按钮不可点击。 - 实现移除操作:点击移除按钮,对应书籍从购物车中移除。
- 当所有书籍全部移除时,界面显示文字
购物车为空
- 总价为各书籍价格*购买数量之和
2.页面基本搭建
我们先创建3个文件index.html
,style.css
,main.js
来分别存放我们的HTML,CSS,JS代码。
先在main.js文件中,实例化一个vue,并增加书籍数据对象。
let vm = new Vue({
el: "#app",
data: {
books:[
{
id:1,
name: '算法导论',
date: '2006-9',
price: 85,
number: 1,
},
{
id:2,
name: 'UNIX编程艺术',
date: '2006-2',
price: 59,
number: 1,
},
{
id:3,
name: '编程珠玑',
date: '2008-10',
price: 39,
number: 1,
},
{
id:4,
name: '代码大全',
date: '2006-3',
price: 128,
number: 1,
}
]
}
});
任何在index.html文件中,搭建页面骨架
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="book in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price}}</td>
<td>
<button type="button">+</button>
{{book.number}}
<button type="button">-</button>
</td>
<td>
<button type="button">移除</button>
</td>
</tr>
</tbody>
</table>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
在style.css文件中设置css样式
table{
border: 1px solid #E9E9E9;
border-collapse: collapse;
border-spacing: 0;
}
th, td{
padding: 8px 16px;
border: 1px solid #E9E9E9;
text-align: left;
}
th{
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
运行效果如下:
这样我们的界面基本上就搭建好了,接下来就是实现各个细节。
3.使用过滤器(filters)实现价格的细节
我们需要对我们价格数据做一些特殊处理后1.增加¥符合;2.保留两位小数
。对于这种需要将vue中的数据做一些格式化操作再输出的需求,我们可以使用vue中的过滤器filters来实现。
定义过滤器格式如下:
new Vue({
el: "#app",
filters: {
//定义一个过滤器showPrice
showPrice: function(price){
return '¥' + price.toFixed(2)
}
}
});
使用过滤器格式:
<!--使用`|`后面跟上过滤器名字来调用过滤器,vue会自动将`|`前面的数据作为参数传入过滤器中-->
<td>{{book.price | showPrice}}</td>
继续完善我们的案例:
先修改main.js文件,增加一个过滤器
let vm = new Vue({
el: "#app",
data: {
books:[
{
id:1,
name: '算法导论',
date: '2006-9',
price: 85,
number: 1,
},
{
id:2,
name: 'UNIX编程艺术',
date: '2006-2',
price: 59,
number: 1,
},
{
id:3,
name: '编程珠玑',
date: '2008-10',
price: 39,
number: 1,
},
{
id:4,
name: '代码大全',
date: '2006-3',
price: 128,
number: 1,
}
]
},
filters: {
//定义一个过滤器showPrice
showPrice: function(price){
return '¥' + price.toFixed(2)
},
}
});
修改index.html文件,对价格数据使用过滤器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="book in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price | showPrice}}</td>
<td>
<button type="button">+</button>
{{book.number}}
<button type="button">-</button>
</td>
<td>
<button type="button">移除</button>
</td>
</tr>
</tbody>
</table>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
效果如下:
后续如果有数据还需要这种格式化输出都可以调用该过滤器。
4.实现购买数量的增减操作
我们可以对数量栏的+
-
按钮绑定点击事件监听,来实现数量的加减。
在index.html文件中,绑定监听事件jiaclick
和jianclick
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="book in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price | showPrice}}</td>
<td>
<button type="button" @click="jiaclick(book)">+</button>
{{book.number}}
<button type="button" @click="jianclick(book)">-</button>
</td>
<td>
<button type="button">移除</button>
</td>
</tr>
</tbody>
</table>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
在main.js文件中,在vue实例的methods中创建对应的事件监听方法jiaclick
和jianclick
。
let vm = new Vue({
el: "#app",
data: {
books:[
{
id:1,
name: '算法导论',
date: '2006-9',
price: 85,
number: 1,
},
{
id:2,
name: 'UNIX编程艺术',
date: '2006-2',
price: 59,
number: 1,
},
{
id:3,
name: '编程珠玑',
date: '2008-10',
price: 39,
number: 1,
},
{
id:4,
name: '代码大全',
date: '2006-3',
price: 128,
number: 1,
}
]
},
filters: {
//定义一个过滤器showPrice
showPrice: function(price){
return '¥' + price.toFixed(2)
},
},
methods:{
//+按钮点击事件方法
jiaclick: function(book){
return book.number++;
},
//-按钮点击事件方法
jianclick: function(book){
return book.number--;
}
}
});
此时效果如下:
5.实现当数量为1时,-
按钮不可点击
我们通过当数量为1时,给-
按钮标签添加disabled属性来实现。
修改index.html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="book in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price | showPrice}}</td>
<td>
<button type="button" @click="jiaclick(book)">+</button>
{{book.number}}
<!--:disabled="表达式/变量"当后面的表达式或变量为true时,添加disabled属性-->
<button type="button" @click="jianclick(book)" :disabled="book.number<=1">-</button>
</td>
<td>
<button type="button">移除</button>
</td>
</tr>
</tbody>
</table>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
此时效果如下:
6.实现移除按钮的功能
移除按钮功能的实现,我们依旧使用监听移除按钮的点击事件的方式来实现。
修改index.html文件,给移除按钮绑定事件监听removeclick
。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(book,index) in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price | showPrice}}</td>
<td>
<button type="button" @click="jiaclick(book)">+</button>
{{book.number}}
<!--:disabled="表达式/变量"当后面的表达式或变量为true时,添加disabled属性-->
<button type="button" @click="jianclick(book)" :disabled="book.number<=1">-</button>
</td>
<td>
<button type="button" @click="removeclick(index)">移除</button>
</td>
</tr>
</tbody>
</table>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
在main.js中完成移除按钮事件监听方法removeclick
的定义。
let vm = new Vue({
el: "#app",
data: {
books:[
{
id:1,
name: '算法导论',
date: '2006-9',
price: 85,
number: 1,
},
{
id:2,
name: 'UNIX编程艺术',
date: '2006-2',
price: 59,
number: 1,
},
{
id:3,
name: '编程珠玑',
date: '2008-10',
price: 39,
number: 1,
},
{
id:4,
name: '代码大全',
date: '2006-3',
price: 128,
number: 1,
}
]
},
filters: {
//定义一个过滤器showPrice
showPrice: function(price){
return '¥' + price.toFixed(2)
},
},
methods:{
jiaclick: function(book){
return book.number++;
},
jianclick: function(book){
return book.number--;
},
//增加移除按钮的点击事件
removeclick: function(index){
this.books.splice(index,1);
}
}
});
现在界面效果如下:
7.实现当界面所有书籍都移除时,显示提示信息购物车为空
该功能我们可以使用v-if
和v-else
来实现。
修改index.html文件如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<!--当books列表的长度大于0时,才展示table列表-->
<div v-if="books.length>0">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(book,index) in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price | showPrice}}</td>
<td>
<button type="button" @click="jiaclick(book)">+</button>
{{book.number}}
<!--:disabled="表达式/变量"当后面的表达式或变量为true时,添加disabled属性-->
<button type="button" @click="jianclick(book)" :disabled="book.number<=1">-</button>
</td>
<td>
<button type="button" @click="removeclick(index)">移除</button>
</td>
</tr>
</tbody>
</table>
</div>
<!--如果books的长度<=0,则展示该标签-->
<div v-else>
<h3>购物车为空</h3>
</div>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
效果如下:
8.实现总价的计算
总价的计算我们可以使用计算属性来实现。
先修改main.js文件,添加总价的计算属性
let vm = new Vue({
el: "#app",
data: {
books:[
{
id:1,
name: '算法导论',
date: '2006-9',
price: 85,
number: 1,
},
{
id:2,
name: 'UNIX编程艺术',
date: '2006-2',
price: 59,
number: 1,
},
{
id:3,
name: '编程珠玑',
date: '2008-10',
price: 39,
number: 1,
},
{
id:4,
name: '代码大全',
date: '2006-3',
price: 128,
number: 1,
}
]
},
filters: {
//定义一个过滤器showPrice
showPrice: function(price){
return '¥' + price.toFixed(2)
},
},
methods:{
jiaclick: function(book){
return book.number++;
},
jianclick: function(book){
return book.number--;
},
//增加移除按钮的点击事件
removeclick: function(index){
this.books.splice(index,1);
}
},
computed:{
// 定义总价的计算属性
totalPrice: function(){
let totalprice = 0;
for (let i in this.books){
totalprice = totalprice + this.books[i].price*this.books[i].number;
};
return totalprice;
}
}
});
修改index.html文件,调用总价的计算属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
</head>
<body>
<div id="app">
<!--当books列表的长度大于0时,才展示table列表-->
<div v-if="books.length>0">
<table>
<thead>
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(book,index) in books">
<td>{{book.id}}</td>
<td>{{book.name}}</td>
<td>{{book.date}}</td>
<td>{{book.price | showPrice}}</td>
<td>
<button type="button" @click="jiaclick(book)">+</button>
{{book.number}}
<!--:disabled="表达式/变量"当后面的表达式或变量为true时,添加disabled属性-->
<button type="button" @click="jianclick(book)" :disabled="book.number<=1">-</button>
</td>
<td>
<button type="button" @click="removeclick(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<!--使用计算属性来渲染总价-->
<div>
总价:{{totalPrice | showPrice}}
</div>
</div>
<!--如果books的长度<=0,则展示该标签-->
<div v-else>
<h3>购物车为空</h3>
</div>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script src="./main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
最终效果如下:
到这里该案例的功能点基本上都实现了👏👏👏。