安装cube-ui
vue add cube-ui
配置router
需要验证时添加meta标签,确认哪个路由需要受保护
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Login from './views/Login.vue'
import {store} from 'vuex'
Vue.use(Router)
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [{
path: '/',
name: 'home',
component: Home
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/about',
name: 'about',
meta: {
auth: true
},
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( /* webpackChunkName: "about" */ './views/About.vue')
}
]
})
router.beforeEach((to, from, next) => {
if (to.meta.auth) {
// 需要认证,则检查令牌
if (store.state.token) {
next()
} else {
// 去登陆
next({
path: '/login',
query: {
redirect: to.path
}
})
}
} else {
next()
}
})
export default router
在store中设置全局token
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
token: ''
},
mutations: {
setToken(state, token) {
state.token = token
}
},
actions: {
}
})
Login.vue组件写入
<template>
<cube-form :model="model" :schema="schema" @validate="handlerValidate" @submit="handlerLogin"></cube-form>
</template>
<script>
import { type } from 'os';
import { log } from 'util';
export default {
data () {
return {
model: {
username: '',
password: ''
},
schema: {
fields: [
{
type: 'input',
modelKey: 'username',
label: '用户名',
props: {
placeholder: '请输入用户名'
},
rules: {
required: true
},
messages: {
required: '用户名为必填项'
},
trigger: 'blur'
},
{
type: 'input',
modelKey: 'password',
label: '密码',
props: {
placeholder: '请输入密码',
type: 'password',
eye: {
open: false
}
},
rules: {
required: true
},
messages: {
required: '密码为必填项'
},
trigger: 'blur'
},
{
type: 'submit',
label: '登录'
}
]
}
}
},
methods: {
handlerLogin (e) {
e.preventDefault()
console.log('登录')
},
handlerValidate (ret) {
console.log('校验' + ret)
},
},
}
</script>
<style lang="scss" scoped>
</style>
main.js中全局注册axios
import Vue from 'vue'
import './cube-ui'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
Vue.config.productionTip = false
Vue.prototype.axios = axios
Login组件中写入,异步请求服务器比对用户名和密码,成功后跳转到原先未登录前的页面
<template>
<cube-form :model="model" :schema="schema" @validate="handleValidate" @submit="handleLogin"></cube-form>
</template>
<script>
export default {
data () {
return {
model: {
username: '',
password: ''
},
schema: {
fields: [
{
type: 'input',
modelKey: 'username',
label: '用户名',
props: {
placeholder: '请输入用户名'
},
rules: {
required: true
},
messages: {
required: '用户名为必填项'
},
trigger: 'blur'
},
{
type: 'input',
modelKey: 'password',
label: '密码',
props: {
placeholder: '请输入密码',
type: 'password',
eye: {
open: false
}
},
rules: {
required: true
},
messages: {
required: '密码为必填项'
},
trigger: 'blur'
},
{
type: 'submit',
label: '登录'
}
]
}
}
},
methods: {
async handleLogin (e) {
e.preventDefault()
const res = await this.axios.get('/api/login', {
params: {
username: this.model.username,
password: this.model.password
}
})
console.log(res)
const { code, token, message } = res.data
console.log(code, token, message)
if (code === 0) {
// 登录成功
localStorage.setItem('token', token) // 缓存至本地
this.$store.commit('setToken', token)
let redirect = '/'
if (this.$route.query.redirect) {
redirect = this.$route.query.redirect
}
this.$router.push(redirect)
} else {
const toast = this.$createToast({
time: 2000,
txt: message || '登录失败',
type: 'error'
})
toast.show()
}
},
handleValidate (ret) {
console.log('校验' + ret)
}
}
}
</script>
既然要请求服务器了,我们可以在vue.config.js的configureWebpack中的devServer中写一个开发用的自定义服务器
module.exports = {
css: {
loaderOptions: {
stylus: {
'resolve url': true,
'import': [
'./src/theme'
]
}
}
},
pluginOptions: {
'cube-ui': {
postCompile: true,
theme: true
}
},
configureWebpack: {
devServer: {
before(app) {
app.get('/api/login', function (req, res) {
const {username, password} = req.query
if (username === 'Vansal' && password === '123') {
res.json({
code: 0,
token: 'haha'
})
} else {
res.json({
code: -1,
message: '用户名或密码错误'
})
}
})
}
}
}
}
当我们每次请求服务器是都要携带token,我们可以设置所有的http请求预先放入token令牌
根目录下新建http-interceptor.js文件,写入
import axios from 'axios'
import store from './store'
axios.interceptors.request.use(
config => {
if (store.state.token) {
config.headers.token = store.state.token
return config
}
}
)
这个文件只要执行一次就可以了,所以只要把它放入main.js中就可以了,因为导入后会自动执行一遍
import interceptor from './http-interceptor'
设置登出,app.vue中写入
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>|
<router-link to="/about">About</router-link>|
<router-link to="/login" v-if="!isLogin">login</router-link>|
<a @click="logout" v-if="isLogin">logout</a>
</div>
<router-view />
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['isLogin'])
},
methods: {
logout () {
this.axios.get('/api/logout')
}
}
}
</script>
this.axios.get('/api/logout') 登出时发送了请求
所以在vue.config.js中加入
app.get('/api/logout', function (req, res) {
res.json({
code: -1
})
})
在响应回来之前,我们要判断用户是否已注销或token令牌是否已过期,所以在http-interceptor.js中配置响应拦截器
// 响应拦截器
axios.interceptors.response.use(
response => {
// 如果code是-1,说明用户已注销或token已过期
// 此时需要重新登录,并且清除本地的缓存信息
if (response.status === 200) {
const data = response.data
if (data.code === -1) {
store.commit('setToken', '')
localStorage.removeItem('token')
// 跳转至登录页面
router.push({
path: '/login',
query: {
redirect: router.currentRoute.path
}
})
}
}
return response
}
)