vue全家桶+element-UI搭建後臺管理系統(4)“:登入攔截,登陸後才可以操作”
首先明白如何實現登入攔截,他的原理是什麼?
這裡主要用到的是路由攔截,在路由表裡新增一個欄位:requireAuth
,用於判斷該路由的訪問是否需要登入;定義完路由後,我們主要是利用vue-router
提供的鉤子函式beforeEach()
對路由進行判斷。現在 我們開始......
首先科普下狗子函式:
每個鉤子方法接收三個引數:
* to: Route: 即將要進入的目標 路由物件
* from: Route: 當前導航正要離開的路由
* next: Function: 一定要呼叫該方法來 resolve 這個鉤子。執行效果依賴 next 方法的呼叫引數。
* next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
* next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了(可能是使用者手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
* next(‘/’) 或者 next({ path: ‘/’ }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。
1、編寫一個登入頁面login.vue
<template> <el-container> <el-form :model="ruleLogin" status-icon :rules="loginRules" ref="ruleLogin" class="demo-ruleForm"> <el-form-item prop="userName"> <el-input type="password" v-model="ruleLogin.userName" auto-complete="off" placeholder="請輸入賬號"></el-input> </el-form-item> <el-form-item prop="passWord"> <el-input type="password" v-model="ruleLogin.passWord" auto-complete="off" placeholder="請輸入密碼"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleLogin')">登入</el-button> <el-button @click="register()">註冊</el-button> </el-form-item> </el-form> </el-container> </template> <script> export default { data() { var checkName = (rule, value, callback) => { if (!value) { return callback(new Error('使用者名稱不能為空')); } callback(); }; var validatePass = (rule, value, callback) => { if (value === '') { callback(new Error('請輸入密碼')); } else { if (this.ruleLogin.passWord !== '') { callback(); } } }; return { ruleLogin: { userName:'', passWord: '' }, loginRules: { userName: [ { validator: checkName, trigger: 'blur' } ], passWord: [ { validator: validatePass, trigger: 'blur' } ] } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); }, register() { } } } </script> <style scoped lang="scss"> .el-container{ position: absolute; top:0; left:0; bottom:0; right: 0; display: flex; display: -webkit-flex; align-items: center; -webkit-align-items: center; justify-content: center; -webkit-justify-content: center; background-color: aquamarine; .el-form{ border-radius: 20px; background-color: #ffffff; padding: 40px 30px; .el-form-item{ display: flex; display: -webkit-flex; align-items: center; -webkit-align-items: center; justify-content: space-between; .el-input{ flex:1; -webkit-flex: 1; width: 260px; display: flex; display: -webkit-flex; align-items: center; -webkit-align-items: center; input{ flex:1; -webkit-flex: 1; } } } } } </style>
2、修改路由,新增登入驗證欄位requireAuth
import Vue from 'vue' import Router from 'vue-router' import index from '@/views/index'//主頁 import login from '@/views/login'//登入 Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'index', component: index, meta:{ requireAuth:true,// 新增該欄位,表示進入這個路由是需要登入的 } }, { path:'/login', name:'登入', component:login } ] })
3、現在實現簡單的路由攔截:修改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 router from './router' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import 'font-awesome/css/font-awesome.css' Vue.use(ElementUI); Vue.config.productionTip = false //路由攔截器 router.beforeEach((to, from, next) => { if (to.meta.requireAuth) { // 判斷該路由是否需要登入許可權 next({ path: '/login', // 將跳轉的路由path作為引數,登入成功後跳轉到該路由 }) }else { next(); } }) /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
到這裡簡單的路由攔截器已經實現了,有的同學會問,如何在本地儲存登入狀態呢?,如何在伺服器儲存登入狀態?如何實現本地和伺服器登入驗證呢?比如tooken?
4、想實現本地儲存登入資訊tooken ,那我們先用下vuex吧,不明白的同學自行百度下
(1)、安裝vuex: cnpm install vuex -S
(2)、在main.js引入vuex:
import router from './router'//匯入路由表
/* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })
完整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 router from './router'//匯入路由表 import store from './store'//匯入store import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import 'font-awesome/css/font-awesome.css' Vue.use(ElementUI); Vue.config.productionTip = false //路由攔截器 router.beforeEach((to, from, next) => { if (to.meta.requireAuth) { // 判斷該路由是否需要登入許可權 next({ path: '/login', // 將跳轉的路由path作為引數,登入成功後跳轉到該路由 }) }else { next(); } }) /* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })
(3)、store->index.js:
import Vue from 'vue' import Vuex from 'vuex' import user from './modules/user'//匯入user Vue.use(Vuex)//使用vuex export default new Vuex.Store({ modules: { user, }, strict: process.env.NODE_ENV !== 'production', //在非生產環境下,使用嚴格模式 })
store->modules->user.js
import Vue from 'vue' export const USER_SIGNIN = 'USER_SIGNIN' //登入成功 export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登入 export default { state: JSON.parse(sessionStorage.getItem('user')) || {}, mutations: { [USER_SIGNIN](state, user) { sessionStorage.setItem('user', JSON.stringify(user)) Object.assign(state, user)//Object.assign() 方法用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件。它將返回目標物件。 }, [USER_SIGNOUT](state) { sessionStorage.removeItem('user') Object.keys(state).forEach(k => Vue.delete(state, k))//Object.keys() 方法會返回一個由一個給定物件的自身可列舉屬性組成的陣列,陣列中屬性名的排列順序和使用 for...in 迴圈遍歷該物件時返回的順序一致 (兩者的主要區別是 一個 for-in 迴圈還會列舉其原型鏈上的屬性)。 } }, actions: { [USER_SIGNIN]({commit}, user) { commit(USER_SIGNIN, user) }, [USER_SIGNOUT]({commit}) { commit(USER_SIGNOUT) } } }修改login.vue元件,先匯入