亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue登錄后添加動態(tài)路由并跳轉(zhuǎn)的實(shí)踐分享

 更新時間:2023年07月19日 10:01:48   作者:前端學(xué)習(xí)筆記_zxh  
這篇文章講給大家詳細(xì)介紹一下Vue如何實(shí)現(xiàn)登錄后添加動態(tài)路由并跳轉(zhuǎn),文章通過代碼示例介紹的非常詳細(xì),對我們的學(xué)習(xí)或工作有一定的的幫助,需要的朋友可以參考下

前言

項(xiàng)目框架:Vue3 + TypeScript

有這樣一個需求,系統(tǒng)默認(rèn)只有最基礎(chǔ)的幾個路由,如登錄、404等,其它路由需要在登錄后動態(tài)添加。系統(tǒng)沒有固定首頁,登錄完成后跳轉(zhuǎn)至動態(tài)菜單的第一個菜單頁。

分析

這一邏輯乍一看很簡單,其實(shí)有很多小坑在里面。其中最容易踩的的坑是動態(tài)路由尚未渲染完成就已經(jīng)觸發(fā)路由跳轉(zhuǎn)了,這時候肯定是404,因?yàn)槁酚刹⒉淮嬖?;另一個容易踩的坑是路由重復(fù)加載,此時頁面會顯示空白,需要手動刷新才能正常顯示。

首先想到的就是使用 Promise 函數(shù)解決,結(jié)果行不通。addRoute 是一個宏任務(wù) 和 resolve 是微任務(wù),所以 Promise 結(jié)束的時候并不能代表動態(tài)路由已經(jīng)添加完成。

其次又想到使用 async 函數(shù)來確保獲取到登錄成功結(jié)果的時候,路由已經(jīng)添加完成,結(jié)果一番嘗試后依然行不通。因?yàn)樘砑勇酚傻牟僮鞑皇钱惒降?,沒有返回 Promise 對象,因此這里的 await 是不會產(chǎn)生效果的。(PS:事后使用 Promise.all 解決了這一問題,后面的具體方法上會說。)

最后,想到了一個很笨的解決方法,輪詢。實(shí)驗(yàn)過后,確定可以實(shí)現(xiàn),但就如開頭說的,這會顯得很 low ,雖然它最終解決了問題。

實(shí)踐

登錄的操作都是一樣的,所以單獨(dú)拿出來只寫一遍。表單就不做介紹了,就從點(diǎn)擊登錄表單校驗(yàn)通過后說起。

所有登錄的代碼放到一個頁面會顯得臃腫,所以具體登錄的操作邏輯我把它抽離了出來。在 src/utils 目錄下創(chuàng)建一個 auth.ts 文件。

auth.ts

import { useRouteListStore } from '@/store/router'
const routeListStore = useRouteListStore()
// 登錄
export async function Login(data: { username: string; password: string; portal: string; corpCode: string }) {
  const { username, password, portal, corpCode } = data
  try {
    // 登錄接口
    const res = await getLogin({ username, password, portal, corpCode })
    // ...
    // 這里寫保存用戶信息及 token 的邏輯
    // ...
    // 添加路由操作,寫在 pinia 中,后面會說
    await routeListStore.updateRouteList()
    return res
  } catch (err) {
    return err
  }
}

接下來要寫添加路由的具體邏輯。在 src/store 目錄下創(chuàng)建一個 router.ts 文件,添加內(nèi)容如下:(PS:具體文件路徑要結(jié)合具體的項(xiàng)目內(nèi)容,以下路徑及菜單格式僅作為示例)。

根據(jù)處理方式不同,有兩種方案。

方案一:使用 async 函數(shù)

src/store/router.ts

export const useRouteListStore = defineStore('routeList', {
  state: () => ({
    routeList: [],
    breadcrumb: [],
    getRouter: true // 是否需要重新加載路由
  }),
  actions: {
    // 更新菜單并追加路由
    async updateRouteList() {
      const modules = import.meta.glob('../views/**/*.vue')
      // 此為接口請求獲取的菜單
      const list = await getMenus()
      list.forEach((e) => {
        e.route = e.path
        e.component = () => import('@/layout/index.vue')
        e.redirect = `${e.path}/${e.children[0].path}`
        e.children.forEach((item) => {
          item.route = `${e.path}/${item.path}`
          item.component = modules[`../views${item.component}.vue`]
        })
      })
      await addRouteList(list)
      this.getRouter = false
      this.routeList = list
      return true
    },
  }
})

接下來寫動態(tài)添加路由的邏輯,使用 Promise.all 來確保 Pinia 中返回結(jié)果時,動態(tài)路由已經(jīng)加載完成。在 src/router 創(chuàng)建 index.ts 文件,添加內(nèi)容如下:

src/router/index.ts

export function addRouteList(data: any[] = []) {
  return new Promise((resolve) => {
    const promises = []
    data.forEach((e) => promises.push(router.addRoute(e)))
    Promise.all(promises).then(() => resolve(true))
  })
}

使用 async 函數(shù)之后,登錄頁的操作將會變得很簡單。

login.vue

import { Login } from '@/utils/auth'
const onSubmit = () => {
  validate().then(() => {
    Login(formState).then(() => {
      router.push(routerStore.routeList[0].path)
    }).catch(err => {
      message.error(err.message)
    })
  })
}

方案二:使用輪詢

輪詢的方案相比于使用 async 函數(shù)要簡單很多,因?yàn)樗恍枰_保登錄后拿到結(jié)果的那一刻,路由是加載完成的。具體實(shí)現(xiàn)代碼如下:

src/store/router.ts

export const useRouteListStore = defineStore('routeList', {
  state: () => ({
    routeList: [],
    breadcrumb: [],
    getRouter: true
  }),
  actions: {
    // 更新菜單并追加路由
    updateRouteList() {
      listMenus().then((res) => {
        const list = res.data
        if (list === null) {
          this.getRouter = false
          router.push('/404')
          return
        }
        list.forEach((e) => {
          e.route = e.path
          e.component = () => import('@/layout/index.vue')
          e.children.forEach((item) => {
            item.route = `${e.path}/${item.path}`
            item.component = modules[`../views${item.component}.vue`]
          })
        })
        addRouteList(list)
        this.getRouter = false
        this.routeList = list
      })
  }
})

src/router/index.ts

export function addRouteList(data: any[] = []) {
  data.forEach((e) => {
    router.addRoute(e)
  })
}

輪詢的好處是邏輯簡單,唯一麻煩的一點(diǎn)就是在登錄后添加一個定時器去定期獲取路由是否加載完成。之所以要加定時器是因?yàn)楂@取菜單是異步請求,而程序執(zhí)行時很快的,所以要確保執(zhí)行路由跳轉(zhuǎn)命令時菜單是加載完成的。

login.vue

import { ref, onBeforeUnmount } from 'vue'
import { useRouter } from 'vue-router'
import { useRouteListStore } from '@/store/router'
const routerStore = useRouteListStore()
import { Login } from '@/utils/auth'
const router = useRouter()
// 每0.5s判斷一次菜單是否加載完成,最多判斷30次,超過則說明網(wǎng)絡(luò)環(huán)境極差
const timer = ref(null)
const onSubmit = () => {
  validate().then(() => {
    Login(formState).then(() => {
    let i = 0
      timer.value = setInterval(() => {
        if (routerStore.routeList[0].path) {
          router.push(routerStore.routeList[0].path)
        }
        i++
        if (i > 30) {
          clearInterval(timer.value)
          timer.value = null
          i = null
          message.error('當(dāng)前網(wǎng)絡(luò)環(huán)境較差!')
          spinning.value = false
        }
      }, 500)
    })
  })
}
// 不要忘記清除定時器
onBeforeUnmount(() => {
  clearInterval(timer.value)
  timer.value = null
})

補(bǔ)充

以上代碼只能保證系統(tǒng)初次登錄后可以正常跳轉(zhuǎn)頁面,如果退出當(dāng)前賬號,重新登錄或者更換賬號登錄,會出現(xiàn)路由重復(fù)加載的問題,也就是文章開頭所說的另一個容易踩的坑。這個坑解決起來并不困難,只要注意到了,很容易就可以解決。

解決思路是添加路由前置守衛(wèi),同時在 Pinia 中添加一個字段判斷當(dāng)前路由是否需要重新加載即可。具體代碼如下:

import Cookies from 'js-cookie'
import { useRouteListStore } from '@/store/router'
// 前置守衛(wèi)
router.beforeEach(async (to, from, next) => {
  const token = Cookies.get('token')
  if (!token) {
    next({ path: '/login' })
  } else {
    const routerStore = useRouteListStore()
    routerStore.addBreadcrumb(to)
    // 判斷菜單是否存在且是否需要重新加載
    if (routerStore.routeList.length === 0 && routerStore.getRouter) {
      await routerStore.updateRouteList()
      next({ path: to.path, query: to.query })
    } else {
      next()
    }
  }
})

如對本文有疑問或不同看法,歡迎在評論區(qū)指出。

以上就是Vue登錄后添加動態(tài)路由并跳轉(zhuǎn)的實(shí)踐分享的詳細(xì)內(nèi)容,更多關(guān)于Vue添加動態(tài)路由并跳轉(zhuǎn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue自適應(yīng)布局postcss-px2rem詳解

    vue自適應(yīng)布局postcss-px2rem詳解

    這篇文章主要介紹了vue自適應(yīng)布局(postcss-px2rem)的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2022-05-05
  • vue3+ts+EsLint+Prettier規(guī)范代碼的方法實(shí)現(xiàn)

    vue3+ts+EsLint+Prettier規(guī)范代碼的方法實(shí)現(xiàn)

    本文主要介紹在Vue3中使用TypeScript做開發(fā)時,如何安裝與配置EsLint和Prettier,以提高編碼規(guī)范。感興趣的可以了解一下
    2021-10-10
  • vue 中 get / delete 傳遞數(shù)組參數(shù)方法

    vue 中 get / delete 傳遞數(shù)組參數(shù)方法

    這篇文章主要介紹了vue 中 get / delete 傳遞數(shù)組參數(shù)方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • vue3.x使用swiper實(shí)現(xiàn)卡片輪播

    vue3.x使用swiper實(shí)現(xiàn)卡片輪播

    這篇文章主要為大家詳細(xì)介紹了vue3.x使用swiper實(shí)現(xiàn)卡片輪播,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Vue3使用indexDB緩存靜態(tài)資源的示例代碼

    Vue3使用indexDB緩存靜態(tài)資源的示例代碼

    IndexedDB 是一個瀏覽器內(nèi)建的數(shù)據(jù)庫,它可以存放對象格式的數(shù)據(jù),默認(rèn)情況下,瀏覽器會將自身所在的硬盤位置剩余容量全部作為indexedDB的存儲容量,本文給大家介紹了Vue3使用indexDB緩存靜態(tài)資源,需要的朋友可以參考下
    2024-10-10
  • Monaco-editor 的 JSON Schema 配置及使用介紹

    Monaco-editor 的 JSON Schema 配置及使用介紹

    這篇文章主要為大家介紹了Monaco-editor 的 JSON Schema 配置及使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • antd vue表格可編輯單元格以及求和實(shí)現(xiàn)方式

    antd vue表格可編輯單元格以及求和實(shí)現(xiàn)方式

    這篇文章主要介紹了antd vue表格可編輯單元格以及求和實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • vue如何獲取光標(biāo)位置

    vue如何獲取光標(biāo)位置

    這篇文章主要介紹了vue獲取光標(biāo)位置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Vue組件傳參11種方式舉例介紹

    Vue組件傳參11種方式舉例介紹

    這篇文章主要給大家介紹了關(guān)于Vue組件傳參11種方式的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • 利用Vue與D3.js創(chuàng)建交互式數(shù)據(jù)可視化

    利用Vue與D3.js創(chuàng)建交互式數(shù)據(jù)可視化

    在現(xiàn)代Web開發(fā)中,數(shù)據(jù)可視化是一個引人矚目的熱點(diǎn)領(lǐng)域,從簡單的圖表到復(fù)雜的交互式儀表盤,數(shù)據(jù)可視化能夠幫助用戶更好地理解數(shù)據(jù),而Vue與D3.js的結(jié)合則為我們提供了構(gòu)建這些可視化效果的強(qiáng)大工具,本文將向您展示如何利用Vue與D3.js創(chuàng)建一個基本的交互式數(shù)據(jù)可視化項(xiàng)目
    2025-02-02

最新評論