很久没有更新博客,最近终于学完了Vue全家桶,总结使用Vue开发的快餐店POS系统。系统采用的技术栈是Vue+Element+vueRouter+webpack,成果展示点击查看。
项目初始化
使用Mockplus将POS系统的框线图画出来,再使用技术实现,可以保持开发时的整体性,避免大范围修改。
webpack+Vue-cli搭建项目结构
1
2
|
npm install vue-cli -g
vue init webpack vpos
|
输入npm run dev
,如果能正常显示说明安装正确。
新建Pos组件,在该文件中编写vue模板的架构。
修改路由文件,引入Pos模板组件,将入口文件更改为Pos组件。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import Vue from 'vue'
import Router from 'vue-router'
import Pos from '@/components/page/Pos'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Pos',
component: Pos
}
]
})
|
配置使用项目图标
在阿里巴巴图标库中,新建项目,添加需要的图标到项目中。选择Font Class查看在线链接,在项目首页中引入。
<link rel="stylesheet" href="http://at.alicdn.com/t/font_999368_80h0n0s7xy9.css">
在"我的项目"中选择单个图标,直接复制代码就可以在项目中使用了。
1
|
<i class="icon iconfont icon-hanbao"></i>
|
编写侧边栏导航组件
在src/components
目录下,新建common和page文件夹,前者存放共用组件,后者存放页面模板文件。
在common文件夹下新建leftNav.vue文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<template>
<div class="left-nav">
<ul>
<li><i class="icon iconfont icon-hanbao"></i>
<div>商品</div>
</li>
<li><i class="icon iconfont icon-dianpu"></i>
<div>店铺</div>
</li>
<li><i class="icon iconfont icon-goumai"></i>
<div>收银</div>
</li>
<li><i class="icon iconfont icon-huiyuanqia"></i>
<div>会员</div>
</li>
<li><i class="icon iconfont icon-gongnengjianyi"></i>
<div>设置</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name:'leftNav',
data(){
return{}
}
}
</script>
|
然后给组件设置一些CSS样式,就算写好了。再在App.vue中引入leftNav组件,然后在构造器里添加components属性,放入leftNav组件。最后在<template>
区域使用就可以查看了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<template>
<div id="app">
<leftNav></leftNav>
<div class="main">
<router-view/>
</div>
</div>
</template>
<script>
import leftNav from '@/components/common/leftNav'
export default {
name: 'App',
components:{
leftNav
}
}
</script>
|
引入Element组件库
1
|
npm install element-ui --save
|
在main.js中引入
1
2
3
4
5
|
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(ElementUI);
|
用Element标签实现栅栏布局
在Pos.vue中添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<template>
<div class="pos">
<div>
<el-row>
<el-col :span='7'>
我是订单栏
</el-col>
<el-col :span="17">
我是商品栏
</el-col>
</el-row>
</div>
</div>
</template>
|
实现两栏高度100%
给对应的<el-row>
添加id,在使用钩子函数设置高度。
1
2
3
4
|
mounted:function(){
var orderHeight=document.body.clientHeight;
document.getElementById("order-list").style.height=orderHeight+'px';
}
|
用el-tabs制作标签页,el-table组件制作表格,el-button设置按钮。具体使用方法可以到Element的官网查看API。
1
2
3
4
5
6
7
8
9
10
11
|
<el-table :data="tableData" border style="width:100%">
<el-table-column prop="goodsName" label="商品名称"></el-table-column>
<el-table-column prop="count" label="数量"></el-table-column>
<el-table-column prop="price" label="金额"></el-table-column>
<el-table-column label="操作" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="small">删除</el-button>
<el-button type="text" size="small">增加</el-button>
</template>
</el-table-column>
</el-table>
|
其中:data用于绑定数据源,tableData为示例数据数组,实际开发中可以使用axios从后台读取。
在<el-col :span=17>
标签里增加一个层,然后在层内使用无序列表来布局常用商品。
1
2
3
4
5
6
7
8
|
<div class="often-goods">
<div class="title">常用商品</div>
<div class="often-goods-list">
<ul>
<li v-for="goods in oftenGoods"><span>{{goods.goodsName}}</span><span class="o-price">¥{{goods.price}}</span></li>
</ul>
</div>
</div>
|
在vue构造器里声明食品数组typeGoods,再用v-for来输出数据。
1
2
3
4
5
|
<li v-for="goods in typeGoods[0]">
<span class="foodImg"><img :src="goods.goodsImg" width="100%" height="60px"></span>
<span class="foodName">{{goods.goodsName}}</span>
<span class="foodPrice">¥{{goods.price}}</span>
</li>
|
使用方法实现对商品操作
添加商品到订单界面
在vue的构造器里加入methods方法,在methods方法里再加入addOrderList方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
methods:{
//添加订单列表的方法
addOrderList(goods){
this.totalCount=0; //汇总数量清0
this.totalMoney=0;
let isHave=false;
//判断是否这个商品已经存在于订单列表
for (let i=0; i<this.tableData.length;i++){
console.log(this.tableData[i].goodsId);
if(this.tableData[i].goodsId==goods.goodsId){
isHave=true; //存在
}
}
//根据isHave的值判断订单列表中是否已经有此商品
if(isHave){
//存在就进行数量添加
let arr = this.tableData.filter(o =>o.goodsId == goods.goodsId);
arr[0].count++;
//console.log(arr);
}else{
//不存在就推入数组
let newGoods={goodsId:goods.goodsId,goodsName:goods.goodsName,price:goods.price,count:1};
this.tableData.push(newGoods);
}
//进行数量和价格的汇总计算
this.sumMoney();
},
// 汇总数量和金额
sumMoney() {
this.totalCount = 0;
this.totalMoney = 0;
if (this.tableData) {
this.tableData.forEach((element) => {
this.totalCount += element.count;
this.totalMoney = this.totalMoney + (element.price * element.count);
})
}
}
}
|
在商品上绑定方法
1
|
<li v-for="goods in typeGoods[0]" @click="addOrderList(goods)"></li>
|
在订单列表中绑定方法
1
|
<el-button type="text" size="small" @click="addOrderList(scope.row)">增加</el-button>
|
删除单个商品:在veu构造器methods属性里增加一个delSingleGoods方法,并接收goods对象为参数,用数组的filter可以轻松删除数组中单个的商品。
删除全部订单商品:清空tableData,totalMoney,totalCount数据即可。
模拟结账
1
2
3
4
5
6
7
8
9
10
11
12
13
|
checkOut() {
if (this.totalCount != 0) {
this.tableData = [];
this.totalCount = 0;
this.totalMoney = 0;
this.$message({
message: '结账成功,感谢你又完成了一笔订单!',
type: 'success'
});
} else {
this.$message.error('购物车为空,不能结账!');
}
}
|