vuex實現登錄狀態的存儲,未登錄狀態不允許瀏覽


基礎思路就是使用vuex狀態管理來存儲登錄狀態(其實就是存一個值,例如token),然后在路由跳轉前進行登錄狀態的判斷,可以使用vue-router的全局前置守衛beforeEach,也可以使用路由獨享的守衛beforeEnter。

導航守衛

正如其名,vue-router``` 提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。 記住參數或查詢的改變並不會觸發進入/離開的導航守衛。你可以通過觀察 $route 對象來應對這些變化,或使用beforeRouteUpdate的組件內守衛。

完整的導航解析流程

  1. 導航被觸發。
  2. 在失活的組件里調用離開守衛。
  3. 調用全局的 beforeEach 守衛。
  4. 在重用的組件里調用 beforeRouteUpdate 守衛 (2.2+)。
  5. 在路由配置里調用 beforeEnter。
  6. 解析異步路由組件。
  7. 在被激活的組件里調用 beforeRouteEnter。
  8. 調用全局的 beforeResolve 守衛 (2.5+)。
  9. 導航被確認。
  10. 調用全局的 afterEach 鈎子。
  11. 觸發 DOM 更新。
  12. 用創建好的實例調用 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):中斷當前的導航。如果瀏覽器的 URL 改變了(可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應的地址。 
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) => {
        // ...
      }
    }
  ]
})

還有其他部分守衛,詳情可以看官方文檔https://router.vuejs.org/zh-cn/advanced/navigation-guards.html

安裝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}表示把當前路由信息傳遞過去方便登錄后跳轉回來
          }
      } 
        }
     ]
})

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM