首先明白如何實現登錄攔截,他的原理是什麼?
這裏主要用到的是路由攔截,在路由表裏添加一個字段: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組件,先導入