vuex實現登入狀態的儲存,未登入狀態不允許瀏覽
阿新 • • 發佈:2019-01-25
基礎思路就是使用vuex狀態管理來儲存登入狀態(其實就是存一個值,例如token),然後在路由跳轉前進行登入狀態的判斷,可以使用vue-router的全域性前置守衛beforeEach,也可以使用路由獨享的守衛beforeEnter。
導航守衛
正如其名,vue-router
提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全域性的, 單個路由獨享的, 或者元件級的。
記住引數或查詢的改變並不會觸發進入/離開的導航守衛。你可以通過觀察 $route 物件來應對這些變化,或使用beforeRouteUpdate
的元件內守衛。
完整的導航解析流程
- 導航被觸發。
- 在失活的元件裡呼叫離開守衛。
- 呼叫全域性的 beforeEach 守衛。
- 在重用的元件裡呼叫 beforeRouteUpdate 守衛 (2.2+)。
- 在路由配置裡呼叫 beforeEnter。
- 解析非同步路由元件。
- 在被啟用的元件裡呼叫 beforeRouteEnter。
- 呼叫全域性的 beforeResolve 守衛 (2.5+)。
- 導航被確認。
- 呼叫全域性的 afterEach 鉤子。
- 觸發 DOM 更新。
- 用建立好的例項呼叫 beforeRouteEnter 守衛中傳給 next 的回撥函式。
全域性守衛
你可以使用 router.beforeEach
註冊一個全域性前置守衛
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
當一個導航觸發時,全域性前置守衛按照建立順序呼叫。守衛是非同步解析執行,此時導航在所有守衛 resolve 完之前一直處於 等待中。
每個守衛方法接收三個引數:
to: Route:
即將要進入的目標 路由物件from: Route:
當前導航正要離開的路由next: Function:
一定要呼叫該方法來 resolve 這個鉤子。執行效果依賴 next 方法的呼叫引數。
next():
進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
next(false):
next('/')
或者next({ path: '/' }):
跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。 next(error):
(2.4.0+) 如果傳入 next 的引數是一個 Error 例項,則導航會被終止且該錯誤會被傳遞給 router.onError()
註冊過的回撥。 確保要呼叫 next 方法,否則鉤子就不會被 resolved。
路由獨享的守衛
你可以在路由配置上直接定義beforeEnter
守衛:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
還有其他部分守衛,詳情可以看官方文件vue-router
安裝vuex後
建立store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const state = {
isLogin: 0
}
const mutations = {
changeLogin(state,status){
state.isLogin = status;
}
}
const actions = {
loginAction({commit}){
commit('changeLogin',1);
}
}
export default new Vuex.Store({
state,
actions,
mutations
})
login.vue中
引入import { mapActions,mapState } from 'vuex'
接著進行登入狀態的改變,base_url就是路徑
export default {
name: 'Login',
data(){
return{
loginForm: {
username: '',
password: '',
},
rules: {
username: [
{ required: true, message: '請輸入使用者名稱', trigger: 'blur' },
],
password: [
{ required: true, message: '請輸入密碼', trigger: 'blur' }
],
},
showLogin: false
}
},
mounted(){
this.showLogin = true;
},
computed: {
...mapState(['isLogin'])
},
methods: {
...mapActions(['loginAction']),
submitForm(formName){
this.$refs[formName].validate((valid) => {
if(valid){
if(this.loginForm.username == 'aaa' && this.loginForm.password == '111'){
console.log('驗證通過');
this.loginAction();
this.$router.push('manage');
}else{
console.log('賬號密碼出錯');
// this.$message.error('賬號密碼出錯');
this.$message({
type: 'error',
message: '賬號密碼出錯'
});
}
console.log('請求地址: ' + base_url);
}else{
console.log('驗證失敗');
return false;
}
})
}
}
}
接下去只要使用路由守衛即可
beforeEach使用例項
router.beforeEach((to,from,next)=>{
if(to.meta.check){
var check = async function(){
const result = await checkUser();
if(result.status == 0){
next();
}else{
alert('使用者未登入');
next({path: '/login'});
}
}
check(); //後臺驗證session
}else{
next();
}
})
beforeEnter使用例項
export default new Router({
routes: [
{
path: '/login',
component: Login
},
{
path: '/manage',
name: '',
component: Manage,
beforeEnter: (to,from,next)=> { //導航守衛
console.log(to)
console.log(from)
if(store.state.isLogin == 1){
console.log('使用者已經登入');
next();
}else{
console.log('使用者未登入');
next({path: '/login',query:{ Rurl: to.fullPath}}); //未登入則跳轉到登陸介面,query:{ Rurl: to.fullPath}表示把當前路由資訊傳遞過去方便登入後跳轉回來
}
}
}
]
})