技术栈
Vue.js 2 + Webpack + Element + Axios + vueRouter.
效果图
图标 Iconfont
在项目开发过程中经常会遇到小图标的使用问题,小图标的使用可以让程序更美观。在这里推荐使用 IconFont,这是阿里巴巴的矢量图标库。
在 Iconfont 中有很多图标,我们可以像逛超市一样,挑选自己喜欢的商品,然后放入购物车。
使用步骤如下:
第一步:拷贝项目下面生成的 fontclass 代码
//at.alicdn.com/t/font_6fwsxglzew154s4i.css
第二步:挑选相应图标并获取类名,应用于页面
<i class="iconfont icon-hanbao"></i>
侧边栏导航组件
LeftNav.vue
<template>
<div class="left-nav">
<ul>
<li>
<i class="iconfont icon-wodezichan"></i>
<div>收银</div>
</li>
<li>
<i class="iconfont icon-dianpu"></i>
<div>店铺</div>
</li>
<li>
<i class="iconfont icon-hanbao"></i>
<div>商品</div>
</li>
<li>
<i class="iconfont icon-31huiyuan"></i>
<div>会员</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'LeftNav'
}
</script>
<style>
.left-nav {
color: #fff;
font-size: 10px;
background-color: #1D8ce0;
float: left;
height: 100%;
width: 5%;
}
.iconfont {
font-size: 24px;
}
.left-nav ul {
padding: 0px;
margin: 0px;
}
.left-nav li {
list-style: none;
text-align: center;
border-bottom: 1px solid #20a0ff;
padding: 10px;
}
</style>
使用 Element 布局
- npm 安装
npm install element-ui --save
- 引入项目
在main.js
中加入以下内容:
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
Vue.use(ElementUI)
右侧内容组件
Main.vue
<template>
<div class="content">
<el-row class="row">
<el-col :span="9" class="col1">
<el-tabs>
<el-tab-pane label="点餐">
<el-table :data="goods" style="width: 100%" stripe>
<el-table-column prop="goodsName" label="商品名称">
</el-table-column>
<el-table-column prop="count" label="数量" width="70">
</el-table-column>
<el-table-column prop="price" label="金额" width="70">
</el-table-column>
<el-table-column label="操作" width="100" fixed="right">
<template scope="scope">
<el-button type="text" size="small" @click="del(scope.row)">删除</el-button>
<el-button type="text" size="small" @click="add(scope.row)">增加</el-button>
</template>
</el-table-column>
</el-table>
<div class="summarize">
<small>数量:</small>{{totalCount}}
<small>金额:</small>{{totalMoney}}元
</div>
<div class="block">
<span class="wrapper">
<el-button type="warning">挂单</el-button>
<el-button type="danger" @click="goods=[]">删除</el-button>
<el-button type="info" @click="checkout">结账</el-button>
</span>
</div>
</el-tab-pane>
<el-tab-pane label="挂单">挂单</el-tab-pane>
<el-tab-pane label="外卖">外卖</el-tab-pane>
</el-tabs>
</el-col>
<el-col :span="15" class="col2">
<div class="common-goods">
<div class="title">常用商品</div>
<div class="goods-list">
<ul>
<li v-for="good in commonGoods" @click="add(good)">
<span v-text="good.goodsName"></span>
<span class="good-price">¥{{good.price}}元</span>
</li>
</ul>
</div>
</div>
<div class="category">
<el-tabs>
<el-tab-pane label="汉堡">
<ul class='type-list'>
<li v-for="hanbao in hanbaoGoods" @click="add(hanbao)">
<span class="img">
![](hanbao.goodsImg)
</span>
<span class="name">{{hanbao.goodsName}}</span>
<span class="price">¥{{hanbao.price}}元</span>
</li>
</ul>
</el-tab-pane>
<el-tab-pane label="小食">
<ul class='type-list'>
<li v-for="xiaoshi in xiaoshiGoods" @click="add(xiaoshi)">
<span class="img">
![](xiaoshi.goodsImg)
</span>
<span class="name">{{xiaoshi.goodsName}}</span>
<span class="price">¥{{xiaoshi.price}}元</span>
</li>
</ul>
</el-tab-pane>
<el-tab-pane label="饮料">
<ul class='type-list'>
<li v-for="yinliao in yinliaoGoods" @click="add(yinliao)">
<span class="img">
![](yinliao.goodsImg)
</span>
<span class="name">{{yinliao.goodsName}}</span>
<span class="price">¥{{yinliao.price}}元</span>
</li>
</ul>
</el-tab-pane>
<el-tab-pane label="套餐">
<ul class='type-list'>
<li v-for="taocan in taocanGoods" @click="add(taocan)">
<span class="img">
![](taocan.goodsImg)
</span>
<span class="name">{{taocan.goodsName}}</span>
<span class="price">¥{{taocan.price}}元</span>
</li>
</ul>
</el-tab-pane>
</el-tabs>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'main',
data() {
return {
goods: [],
commonGoods: [],
hanbaoGoods: [],
xiaoshiGoods: [],
yinliaoGoods: [],
taocanGoods: []
}
},
methods: {
add(good) {
let data = this.goods.filter(g => g.goodsId == good.goodsId)
if (data.length > 0) {
data[0].count++
} else {
// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
let newGood = Object.assign({}, good)
newGood.count = 1
this.goods.push(newGood)
}
},
del(good) {
this.goods = this.goods.filter(g => g.goodsId != good.goodsId)
},
checkout() {
if (this.goods.length != 0) {
this.goods = []
this.totalCount = 0
this.totalMoney = 0
this.$message({
message: '结账成功^_^',
type: 'success'
});
} else {
this.$message.error('不能空结⊙o⊙');
}
}
},
computed: {
totalCount() {
let count = 0
this.goods.forEach(function (element) {
count += element.count
}, this);
return count
},
totalMoney() {
let money = 0
this.goods.forEach(function (element) {
money += element.count * element.price
}, this);
return money
}
},
created() {
// 读取常用商品列表
axios.get('http://jspang.com/DemoApi/oftenGoods.php').then(response => {
this.commonGoods = response.data
}).catch(error => {
console.log(error)
});
// 读取分类商品列表
axios.get('http://jspang.com/DemoApi/typeGoods.php').then(response => {
this.hanbaoGoods = response.data[0]
this.xiaoshiGoods = response.data[1]
this.yinliaoGoods = response.data[2]
this.taocanGoods = response.data[3]
}).catch(error => {
console.log(error)
})
}
}
</script>
<style>
.content,
.row,
.col1,
.col2,
.card {
height: 100%;
}
.col1 {
border-right: 1px solid;
}
.block {
margin-top: 20px;
text-align: center;
}
.title {
height: 42px;
line-height: 42px;
border-bottom: 1px solid #D3DCE6;
background-color: #F9FAFC;
color: #20a0ff;
padding-left: 15px;
}
.goods-list ul li {
list-style: none;
float: left;
border: 1px solid #E5E9F2;
padding: 10px;
margin: 5px;
background-color: #fff;
cursor: pointer;
}
.good-price {
color: #58B7FF;
}
.category {
clear: both;
}
.type-list li {
list-style: none;
width: 30%;
border: 1px solid #E5E9F2;
height: auot;
overflow: hidden;
background-color: #fff;
padding: 2px;
float: left;
margin: 2px;
cursor: pointer;
}
.type-list li span {
display: block;
float: left;
}
.img {
width: 40%;
}
.name {
font-size: 18px;
padding-left: 10px;
color: brown;
}
.price {
font-size: 16px;
padding-left: 10px;
padding-top: 10px;
}
.summarize {
text-align: center;
padding: 10px;
border-bottom: 1px solid #E5E9F2;
}
.summarize small {
margin-left: 40px;
}
</style>
其余代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>awesomepos</title>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_6fwsxglzew154s4i.css">
<style>
html,
body {
margin: 0px;
padding: 0px;
height: 100%;
}
</style>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import router from './router'
Vue.config.productionTip = false
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: {
App
}
})
App.vue
<template>
<div id="app">
<!--左侧导航-->
<LeftNav></LeftNav>
<div class="main">
<router-view></router-view>
</div>
</div>
</template>
<script>
import LeftNav from '@/components/LeftNav'
export default {
name: 'app',
components: {
LeftNav
}
}
</script>
<style>
#app {
font-family: 'Microsoft YaHei', 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
height: 100%;
}
.main {
float: left;
width: 95%;
height: 100%;
overflow: auto;
}
</style>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/components/Main'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'main',
component: Main
}]
})
项目打包
注意事项:
打开 config/index.js
会看到一个 build
属性,这里就是我们打包的基本配置。你在这里可以修改打包的目录,文件名。最重要的是一定要把绝对路径改为相对路径。
把
assetsPublicPath: '/'
改为
assetsPublicPath: './'