鍍金池/ 問答/HTML/ Vue-router-3.0.1 使用router.addRoutes()設(shè)置動

Vue-router-3.0.1 使用router.addRoutes()設(shè)置動態(tài)路由,動態(tài)路由對應(yīng)頁面直接刷新后無效

vue-router-3.0.1 使用router.addRoutes()設(shè)置動態(tài),動態(tài)路由對應(yīng)頁面直接刷新后無效

問題總述

vue-router-3.0.1 使用router.addRoutes()設(shè)置動態(tài)路由,從非動態(tài)路由(router初始化時就存在的路由)頁面跳轉(zhuǎn)到動態(tài)添加的路由的頁面,一切正常。但是,在動態(tài)添加的路由的頁面刷新后(即動態(tài)路由對應(yīng)的頁面自己刷新再路由到自己),路由匹配失敗,頁面無法渲染。

詳細介紹

最近做一個小項目,vue相關(guān)依賴版本如:

    "vue": "^2.5.2",
    "vue-router": "^3.0.1",
    "vuex": "^3.0.1"

項目中,用戶登錄系統(tǒng)前,初始默認路由如下:

/**
 * 靜態(tài)路由
 */
export const staticRouters = [{
    path: '/',
    redirect: '/Home'
}, {
    path: '/Home',
    component: Wrapper,
    children: [{
        path: '',
        name: 'Home',
        component: Home
    }],
    meta: {
        name: '首頁'
    }
}, {
    path: '/DiscussZone',
    component: Wrapper,
    children: [{
        path: '',
        name: 'DiscussZone',
        component: DiscussZone
    }],
    meta: {
        name: '討論區(qū)'
    }
}, {
    path: '/Login',
    name: 'Login',
    component: Login
}, {
    path: '/Register',
    name: 'Register',
    component: Register
}]


/**
 * "個人中心" 子路由
 */
export const myCenterRouter = [{
  path: '',
  redirect: '/MyCenter/myGame'
}, {
  path: 'myGame',
  name: 'myGame',
  component: MyGame,
  meta: {
    name: '我發(fā)布的比賽'
  }
}, {
  path: 'myPostings',
  name: 'myPostings',
  component: MyPostings,
  meta: {
    name: '我的帖子'
  }
}]

/**
 * 動態(tài)路由
 */
export const dynamicRouters = [{
    path: '/MyCenter',
    component: Wrapper,
    children: [{
        path: '',
        component: MyCenter,
        children: myCenterRouter
    }],
    meta: {
        name: '個人中心'
    }
}, {
  path: '*',
  name: '404',
  component: NotFound
}]

// 實例化初始靜態(tài)路由
export default new Router({
    routes: staticRouters
})

在vux中,state中設(shè)置“用戶信息”userInfo字段,其中uid為用戶登錄唯一ID,getters中根據(jù)uid來計算用戶未登錄/登錄狀態(tài)下的可用功能模塊和動態(tài)路由。

// vuex   store/index.js
...
state: {
    userInfo: {
        uid: '',
        role: ''
    }
},
...
getters: {
    // 計算用戶登陸后功能模塊
    userStatusMenu: state => {
        // 根據(jù)vuex中用戶id是否有值,判斷返回的功能菜單模塊
        return !state.userInfo.uid ? state.staticMenuList : state.staticMenuList.concat(state.dynamicMenuList)
    },
    // 計算用戶登陸后動態(tài)路由
    userDynamicRouters: state => {
        // 根據(jù)vuex中用戶id是否有值,判斷返回的動態(tài)路由
        return !state.userInfo.uid ? [] : dynamicRouters
    }
},
mutations: {
    // 保存/更新用戶信息
    SET_USER_INFO(state, userInfo) {
        // state.userInfo = Object.assign({}, state.userInfo, userInfo)
        state.userInfo.uid = userInfo
    }
},

現(xiàn)在要實現(xiàn)如下功能:

用戶登錄前,系統(tǒng)菜單欄只有“首頁”、“討論區(qū)”兩個功能以及對應(yīng)的初始路由。當用戶登錄系統(tǒng)后,動態(tài)添加“個人中心”模塊和其對應(yīng)路由。

個人實現(xiàn)機制如下:

1.用戶登錄前,實例化“首頁”和“討論區(qū)”的初始路由

// router/index.js
...

export default new Router({
    routes: staticRouters
})

...

2.當用戶登錄系統(tǒng)后,將用戶uid寫入瀏覽器sessionStorage中(后面用戶強制刷新頁面時,要使用其判斷),同時提交mutation,設(shè)置vuex中state的uesrInfo.uid字段,此時,uid字段改變,便會重新計算getters中的用戶菜單欄(userStatusMenu),在系統(tǒng)菜單欄動態(tài)添加“個人中心”模塊入口,并計算出該模塊的動態(tài)新增的路由userDynamicRouters

3.vuexgettes計算求得需要動態(tài)新增的路由userDynamicRouters后,使用router.addRoutes`(userDynamicRouters)添加動態(tài)路由到初始化的路由實例對象router`。

login() {
    this.$refs.loginForm.validate((valid) => {
        if (valid) {
            this.$store.commit('SET_USER_INFO', '1234567890')   // 1.登陸成功,vuex設(shè)置用戶id
            sessionStorage.setItem('userUuid', '1234567890')    // 2.session同時存儲id,手動刷新頁面時用它重寫vuex用戶id
            this.$router.addRoutes(this.userDynamicRouters)     // 3.追加動態(tài)路由
            this.$router.push('/Home')                          // 4.跳轉(zhuǎn)到首頁
        } else {
            this.$message.warning('請完善登錄信息!')
            return false
        }
    })
}

至此,初步解決了根據(jù)用戶登錄狀態(tài)動態(tài)生成系統(tǒng)菜單欄功能模塊入口和添加動態(tài)路由功能。登陸后,動態(tài)添加的“個人中心”模塊也可以正常路由。

但是系統(tǒng)頁面F5或者Ctrl+F5刷新后,因為刷新頁面vuexrouter實例會重新初始化到初始狀態(tài),所以vuexstate.userInfo.uid和新增的動態(tài)路由會被刷掉。

所以,在main.js中設(shè)置全局路由守衛(wèi)router.beforeEach(),當頁面刷新時重新判斷登錄時存儲的localStorageuid字段,如果存在,說明用戶登錄,此時如果vuexstate.userInfo.uid如果為空,說明是用戶登錄后進行了刷新頁面的操作,此時會重新向vuex提交mutation,設(shè)置state.userInfo.uid,并重新計算動態(tài)路由,再addRotes()到路由實例router。如下:

// 路由跳轉(zhuǎn)前,登錄狀態(tài)判斷
router.beforeEach((to, from, next) => {
  let userUid = sessionStorage.getItem('userUuid')
  // sessionStorage中userUid不為空,說明用戶已登錄
  if (userUid) {
    // vue中state.userInfo.uid為空,說明用戶刷新了頁面
    if (!store.state.userInfo.uid) {
      store.commit('SET_USER_INFO', userUid)              // 重新提交mutation,設(shè)置state.userInfo.uid
      router.addRoutes(store.getters.userDynamicRouters)  // 添加動態(tài)路由
    }
    next()
  } else {
    // 沒有登錄信息,說明沒有登錄
    if (to.path.indexOf('/MyCenter') !== -1) {
      next('/Home')
    } else {
      next()
    }
  }
});

至此解決了頁面刷新時,動態(tài)路由失效的問題。

但是,But,However,我遇到了一個的坑,也是這篇帖子最后想問的問題??!前面交代那么多,就是想把自己實現(xiàn)的機制描述清楚,方便大神帶帶我,指導(dǎo)一下!!

我遇到的坑和問題

這個坑是:我在“首頁”、“討論區(qū)”這種router初始化時就存在的模塊中點擊菜單跳轉(zhuǎn)到動態(tài)路由模塊“個人中心”包括在這些頁面刷新頁面后再跳轉(zhuǎn)“個人中心”時,一切路由都正常!But,但是,在進入“個人中心”,也就是路由到動態(tài)增加的動態(tài)路由后,在動態(tài)路由頁面直接刷新頁面,卻無法正常路由,頁面沒有渲染??!
找了半天,google,度娘找了一圈,也沒找到處理方法!小弟愚鈍,請大神賜教!!幫忙看看什么原因?

回答
編輯回答
愿如初

有沒有大神指教一下?十分感謝!謝謝啦!

2018年4月20日 11:47