vue+vuex+axios做登入、註冊頁許可權攔截
阿新 • • 發佈:2019-01-10
在GitHub上有很多寫好的模板,這個專案也是基於模板做的。
現在記錄一下我做的過程
1、修改config資料夾裡的dev.env.js裡的BASE_API,把地址改成請求後端的公共部分
BASE_API: '"http://192.168.xx.xx"',
2、接下來就是操作src檔案,先在 views裡寫好vew元件(login.vue,regist.vue),寫好到router裡的index.js裡配置好路徑
login.vue
<template> <div class="login-container"> <el-form autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left" label-width="0px" class="card-box login-form"> <h3 class="title">登入</h3> <el-form-item prop="name"> <span class="svg-container svg-container_login"> <svg-icon icon-class="user"/> </span> <el-input name="name" disabled type="text" v-model="loginForm.name" autoComplete="on" placeholder="使用者名稱"/> </el-form-item> <el-form-item prop="password"> <span class="svg-container"> <svg-icon icon-class="password"></svg-icon> </span> <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="on" placeholder="密碼"></el-input> <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye"/></span> </el-form-item> <el-form-item> <el-button type="primary" style="width:100%;" :loading="loading" @click.native.prevent="handleLogin"> 登入 </el-button> </el-form-item> </el-form> </div> </template> <script> export default { name: 'login', data() { const validateUsername = (rule, value, callback) => { if (value.trim().length<1) { callback(new Error('使用者名稱不能為空')) } else { callback() } }; const validatePass = (rule, value, callback) => { if (value.trim().length < 1) { callback(new Error('密碼不能為空')) } else { callback() } }; return { loginForm: { name: '', password: '' }, loginRules: { name: [{required: true, trigger: 'blur', validator: validateUsername}], password: [{required: true, trigger: 'blur', validator: validatePass}] }, loading: false, pwdType: 'password' } }, methods: { showPwd() { if (this.pwdType === 'password') { this.pwdType = '' } else { this.pwdType = 'password' } }, handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true; this.$store.dispatch('Login', this.loginForm).then(() => { this.loading = false; this.$router.push({path: '/'}); }).catch((e) => { this.loading = false }) } else { console.log('error submit!!') return false } }) } } } </script>
router/index.js
{ path: '/login', component: _import('Login/login'), hidden: true }
3、在api裡的login.js裡寫好與後端對接的介面地址,在stores裡的modules裡的user.js裡定義user,有state,mutations,action,具體的請求操作寫在action裡,login.vue或regist.vue呼叫user.js裡寫好的請求,getter.js裡定義store的getters
api/login.js
import request from '@/utils/request' export function login(name,password) { return request({ url: '/XX/XX', method: 'post', data: { name, password } }) }
stores/modules/user.js
getter.js:import { login,regist,logout } from '@/api/login' import { getToken,setToken } from '@/utils/auth' const user = { state: { name:'', token:'' }, mutations: { SET_NAME: (state, name) => { state.name = name; }, SET_TOKEN: (state, token) => { state.token = token; setToken(token); } }, actions: { // 登入 Login({ commit }, userInfo) { const name = userInfo.name.trim(); const password = userInfo.password.trim(); return new Promise((resolve, reject) => { login(name, password).then(response => { const data = response.data; commit('SET_NAME', data.name); commit('SET_TOKEN', data.token); setName(data.name); setToken(data.token); resolve(response); }).catch(error => { reject(error) }) }) }, // 註冊 Regist({ commit }, userInfo) { const name= userInfo.name.trim(); const password = userInfo.password.trim(); return new Promise((resolve, reject) => { regist(name, password).then(response => { const data = response.data; commit('SET_NAME', data.name); commit('SET_TOKEN', data.token); setName(data.name);setToken(data.token); resolve(response); }).catch(error => { reject(error) }) }) }, // 登出 LogOut({ commit, state }) { return new Promise((resolve, reject) => { logout().then(response => { commit('SET_NAME', ''); commit('SET_TOKEN', ''); setName(''); setToken(false); //removeName(); //removeToken(); resolve(response); }).catch(error => { reject(error) }) }) }, // 前端 登出 FedLogOut({ commit }) { return new Promise(resolve => { setToken(false); commit('SET_TOKEN', false); resolve() }) } } } export default user
const getters={
name:state=>state.user.name,
token:state=>state.user.token
}
export default getter
4、在utils裡的auth.js裡對cookies進行操作,寫入,讀取,刪除使用者許可權,是否登入的標誌等
import Cookies from 'js-cookies'
export function setName(name) {
return Cookies.set("name", name);
}
export function getName() {
return Cookies.get("name");
}
export function setToken(token) {
return Cookies.set("token", token);
}
export function getToken() {
return Cookies.get("token");
}
5、在permission.js裡寫白名單,對白名單以外的跳轉進行攔截然後跳轉登入,同時判斷使用者許可權,是否登入,等import router from './router'
import store from './store'
import NProgress from 'nprogress' // Progress 進度條
import 'nprogress/nprogress.css'// Progress 進度條樣式
import {Message} from 'element-ui'
import {getName, getToken} from "@/utils/auth"; // 驗權
const whiteList = ['/login', '/regist']; // 不重定向白名單
router.beforeEach((to, from, next) => {
NProgress.start();
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
if (getToken()==="true") {
next();
NProgress.done()
} else {
next({path: '/login'});
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done() // 結束Progress
})
6、utils裡的request.js裡寫攔截碼,對後端返回的特定碼進行攔截然後做相應的操作import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '../store'
// 建立axios例項
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 15000 // 請求超時時間
});
// respone攔截器
service.interceptors.response.use(
response => {
/**
* code為非200是拋錯 可結合自己業務進行修改
*/
const res = response.data;
//const res = response;
if (res.code !== '200' && res.code !== 200) {
if (res.code === '4001' || res.code === 4001) {
MessageBox.confirm('使用者名稱或密碼錯誤,請重新登入', '重新登入', {
confirmButtonText: '重新登入',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload()// 為了重新例項化vue-router物件 避免bug
})
})
}
if (res.code === '4009' || res.code === 4009) {
MessageBox.confirm('該使用者名稱已存在,請重新註冊!', '重新註冊', {
confirmButtonText: '重新註冊',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload()// 為了重新例項化vue-router物件 避免bug
})
})
}
return Promise.reject('error')
} else {
return response.data
}
},
error => {
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
});
return Promise.reject(error)
}
)
export default service
以上就是登入註冊的核心部分,寫的不對的地方請指教