Vue Elememt-UI 构建管理后台

安装

我使用的是 vue-cli 初始化项目,命令如下:

1
2
3
npm i -g vue-cli
mkdir my-project && cd my-project
vue init webpack

修改 package.json 文件:

1
2
3
4
5
6
7
8
...
"dependencies": {
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"element-ui": "^2.0.7", // element-ui
"axios": "^0.17.1" // http 请求库
}
...

之后执行 npm install 进行安装依赖,如果安装速度有点慢的话,可以试一下 cnpm ,具体安装和用法自行查找。

简单介绍下项目的目录结构:

1
2
3
4
5
6
7
8
9
10
├─build  // 构建配置
├─config // 配置文件
├─src // vue 开发源文件目录
├────assets // css/js 文件
├────components // vue 组件
├────router // 路由
├────App.vue // 启动组件
├────main.js // 入口文件
├─static // 静态文件目录
├─test // 测试目录

之后在项目根目录执行 npm run dev ,打开浏览器输入 http://localhost:8080 就可以查看了。

目标

  • 登录页面,登录,退出功能
  • 首页,调用接口渲染列表

路由

路由使用的是 vue-router,具体用法可参考 官方文档
我们这里需要两个路由:
src/router/index.js

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
import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/components/Index'
import Login from '@/components/Login'

Vue.use(Router)

const routers = new Router({
routes: [
{
path: '/index',
name: 'index',
component: Index
},
{
path: '/login',
name: 'login',
component: Login
}
]
})

routers.beforeEach((to, from, next) => {
if (to.name !== 'login' && !localStorage.getItem('token')) {
next({path: 'login'})
} else {
next()
}
})

export default routers

登录页面

src/components/Login.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<template>
<div class="login">
<el-form name="aa" :inline="true" label-position="right" label-width="80px">
<el-form-item label="用户名">
<el-input v-model="user.name"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="user.password"></el-input>
</el-form-item>
<el-form-item label=" ">
<el-button type="primary" @click="login()">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>

<script>
import $http from '@/api/'
import config from '@/config'

export default {
data () {
return {
user: {
name: '',
password: ''
}
}
},
mounted: function () {
var token = localStorage.getItem('token')
if (token) {
this.$router.push('/index')
}
},
methods: {
login: function () {
var data = {
grant_type: 'password',
client_id: config.oauth_client_id,
client_secret: config.oauth_secret,
username: this.user.name,
password: this.user.password
}
var _this = this
$http.login(data).then(function (res) {
if (res.status === 200) {
$http.setToken(res.data.access_token)
_this.$message({
showClose: false,
message: '登录成功',
type: 'success'
})
_this.$router.push('/index')
} else {
_this.$message({
showClose: false,
message: '登录失败',
type: 'error'
})
}
})
}
}
}
</script>

<style>
.login{
width: 300px;
margin: 100px auto;
background-color: #ffffff;
padding: 30px 30px 5px;
border-radius: 5px;
}
</style>

首页

src/components/Index.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<template>
<div class="main">
<el-table
stripe
v-loading="loading"
element-loading-background="#dddddd"
:data="tableData"
style="width: 100%">
<el-table-column
prop="id"
label="ID">
</el-table-column>
<el-table-column
prop="name"
label="名称">
</el-table-column>
</el-table>
<el-pagination
background
layout="prev, pager, next"
:total="total"
class="page"
@current-change="pageList">
</el-pagination>
</div>
</template>

<script>
import $http from '@/api/'

export default {
data () {
return {
tableData: [],
total: 0,
loading: false
}
},
mounted: function () {
this.getList()
},
methods: {
pageList: function (page) {
this.search.page = page
this.getList()
},
getList: function () {
var _this = this
_this.loading = true
$http.index().then(function (res) {
if (res.status === 200) {
_this.tableData = res.data.data.lists
_this.total = res.data.data.total
}
_this.loading = false
})
}
}
}
</script>

App

src/App.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<template>
<div id="app">
<el-row v-if="token">
<menus class="left-menu">
<h3 class="logo"><a href="/">Admin</a></h3>
</menus>
<el-col :span="21" :gutter="0" :offset="3">
<el-breadcrumb separator-class="el-icon-arrow-right" class="breadcrumb">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item class="active">列表</el-breadcrumb-item>
</el-breadcrumb>
<el-dropdown @command="operate" class="header">
<img src="/static/image/head.jpg" />
<el-dropdown-menu slot="dropdown" :click="true">
<el-dropdown-item command="/user/profile">基本资料</el-dropdown-item>
<el-dropdown-item command="/logout">安全退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<router-view/>
</el-col>
<el-col :span="21" :gutter="0" :offset="3" class="footer">Copyright © 2017 Flyerboy All Rights Reserved</el-col>
</el-row>

<router-view v-if="!token" />
</div>
</template>

<script>
import Menus from '@/components/Menu'
export default {
name: 'App',
data () {
return {
token: false
}
},
mounted: function () {
this.token = localStorage.getItem('token') ? true : false
},
watch: {
'$route.path': function ($newVal, $oldVal) {
this.token = localStorage.getItem('token') ? true : false
}
},
methods: {
operate: function (command) {
if (command === '/logout') {
localStorage.removeItem('token')
this.$router.push('login')
} else {
this.$router.push(command)
}
}
},
components: {
Menus
}
}
</script>

<style>
body{
margin: 0;
padding: 0;
background-color: #eeeeee;
}
.header{
position: absolute;
top: 5px;
right: 20px;
}
.header img{
width: 38px;
height: 38px;
border-radius: 20px;
border: 1px solid #aaaaaa;
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.main{
padding: 20px;
min-height: 600px;
margin-bottom: 20px;
}
.main table{
background: #ffffff;
}
.left-menu{
background-color: #33374B;
}
.logo{
padding: 20px 0 15px 20px;
font-size: 24px;
border-bottom: 2px solid #3a8ee6;
}
.logo a{
color: #ffffff;
text-decoration: none;
}

.left-menu .el-menu{
border-right: 0;
}
.breadcrumb{
line-height: 40px;
padding: 5px 20px;
background: #ffffff;
}
.breadcrumb span{
color: #069;
font-weight: normal;
}
.breadcrumb .active{
color: #aaaaaa;
}
.page{
margin: 20px 0 0;
margin-left: -10px;
}
.page .el-pager li.number{
background-color: #ffffff;
}
.el-submenu .el-menu-item{
padding-left: 60px !important;
}
.footer{
position: fixed;
bottom: 0;
right: 0;
font-size: 12px;
color: #888888;
padding: 15px 20px;
text-align: center;
background-color: #ffffff;
margin-top: 40px;
}
</style>

调用 API

src/api/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:8000/'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token')


export default {
setToken: function (token) {
localStorage.setItem('token', token)
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token
},
login: function (param) {
return axios.post('oauth/token', param)
},
index: function (params) {
return axios.get('api/user/list', {
params: params
})
}
}

config

src/config.js 这里配置登录 oauth 需要的 client_id 和 secret

1
2
3
4
export default {
oauth_client_id: 2,
oauth_secret: ''
}

main.js

src/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)

Vue.config.productionTip = false

new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})

api 接口

主要用到两个接口,一个是 api/oauth/token 登录获取 token 接口,一个获取列表 api/user/list
第一个接口是用到 laravel oauth,第二个接口直接是一个简单的查询用户列表接口,详细讲会在下一篇文章中讲述。

©版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 & 作者信息

Happy Coding

坚持原创技术分享,您的支持将鼓励我继续创作!
Flyertutor WeChat Pay

WeChat Pay

Flyertutor Alipay

Alipay