溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue 動態(tài)添加路由及生成菜單的方法示例

發(fā)布時間:2020-08-31 04:53:08 來源:腳本之家 閱讀:344 作者:woai3c 欄目:web開發(fā)

寫后臺管理系統(tǒng),估計有不少人遇過這樣的需求:根據(jù)后臺數(shù)據(jù)動態(tài)添加路由和菜單。

為什么這么做呢?因?yàn)椴煌挠脩粲胁煌臋?quán)限,能訪問的頁面是不一樣的。

在網(wǎng)上找了好多資料,終于想到了解決辦法。

動態(tài)生成路由

利用 vue-router 的 addRoutes 方法可以動態(tài)添加路由。

先看一下官方介紹:

router.addRoutes

router.addRoutes(routes: Array<RouteConfig>)

動態(tài)添加更多的路由規(guī)則。參數(shù)必須是一個符合 routes 選項要求的數(shù)組。

舉個例子:

const router = new Router({
  routes: [
    {
      path: '/login',
      name: 'login',
      component: () => import('../components/Login.vue')
    },
    {path: '/', redirect: '/home'},
  ]  
})

上面的代碼和下面的代碼效果是一樣的

const router = new Router({
  routes: [
    {path: '/', redirect: '/home'},
  ]  
})

router.addRoutes([
  {
    path: '/login',
    name: 'login',
    component: () => import('../components/Login.vue')
  }
])

在動態(tài)添加路由的過程中,如果有 404 頁面,一定要放在最后添加,否則在登陸的時候添加完頁面會重定向到 404 頁面。

類似于這樣,這種規(guī)則一定要最后添加。

{path: '*', redirect: '/404'}

動態(tài)生成菜單

假設(shè)后臺返回來的數(shù)據(jù)長這樣

// 左側(cè)菜單欄數(shù)據(jù)
menuItems: [
  {
    name: 'home', // 要跳轉(zhuǎn)的路由名稱 不是路徑
    size: 18, // icon大小
    type: 'md-home', // icon類型
    text: '主頁' // 文本內(nèi)容
  },
  {
    text: '二級菜單',
    type: 'ios-paper',
    children: [
      {
        type: 'ios-grid',
        name: 't1',
        text: '表格'
      },
      {
        text: '三級菜單',
        type: 'ios-paper',
        children: [
          {
            type: 'ios-notifications-outline',
            name: 'msg',
            text: '查看消息'
          },
          {
            type: 'md-lock',
            name: 'password',
            text: '修改密碼'
          },
          {
            type: 'md-person',
            name: 'userinfo',
            text: '基本資料',
          }
        ]
      }
    ]
  }
]

來看看怎么將它轉(zhuǎn)化為菜單欄,我在這里使用了 iview 的組件,不用重復(fù)造輪子。

<!-- 菜單欄 -->
<Menu ref="asideMenu" theme="dark" width="100%" @on-select="gotoPage" 
accordion :open-names="openMenus" :active-name="currentPage" @on-open-change="menuChange">
  <!-- 動態(tài)菜單 -->
  <div v-for="(item, index) in menuItems" :key="index">
    <Submenu v-if="item.children" :name="index">
      <template slot="title">
        <Icon :size="item.size" :type="item.type"/>
        <span v-show="isShowAsideTitle">{{item.text}}</span>
      </template>
      <div v-for="(subItem, i) in item.children" :key="index + i">
        <Submenu v-if="subItem.children" :name="index + '-' + i">
          <template slot="title">
            <Icon :size="subItem.size" :type="subItem.type"/>
            <span v-show="isShowAsideTitle">{{subItem.text}}</span>
          </template>
          <MenuItem class="menu-level-3" v-for="(threeItem, k) in subItem.children" :name="threeItem.name" :key="index + i + k">
            <Icon :size="threeItem.size" :type="threeItem.type"/>
            <span v-show="isShowAsideTitle">{{threeItem.text}}</span>
          </MenuItem>
        </Submenu>
        <MenuItem v-else v-show="isShowAsideTitle" :name="subItem.name">
          <Icon :size="subItem.size" :type="subItem.type"/>
          <span v-show="isShowAsideTitle">{{subItem.text}}</span>
        </MenuItem>
      </div>
    </Submenu>
    <MenuItem v-else :name="item.name">
      <Icon :size="item.size" :type="item.type" />
      <span v-show="isShowAsideTitle">{{item.text}}</span>
    </MenuItem>
  </div>
</Menu>

代碼不用看得太仔細(xì),理解原理即可,其實(shí)就是通過三次 v-for 不停的對子數(shù)組進(jìn)行循環(huán),生成三級菜單。

動態(tài)菜單這樣就可以實(shí)現(xiàn)了。

動態(tài)路由,因?yàn)樯厦嬉呀?jīng)說過了用 addRoutes 來實(shí)現(xiàn),現(xiàn)在看看具體怎么做。

首先,要把項目所有的頁面路由都列出來,再用后臺返回來的數(shù)據(jù)動態(tài)匹配,能匹配上的就把路由加上,不能匹配上的就不加。

最后把這個新生成的路由數(shù)據(jù)用 addRoutes 添加到路由表里。

const asyncRoutes = {
  'home': {
    path: 'home',
    name: 'home',
    component: () => import('../views/Home.vue')
  },
  't1': {
    path: 't1',
    name: 't1',
    component: () => import('../views/T1.vue')
  },
  'password': {
    path: 'password',
    name: 'password',
    component: () => import('../views/Password.vue')
  },
  'msg': {
    path: 'msg',
    name: 'msg',
    component: () => import('../views/Msg.vue')
  },
  'userinfo': {
    path: 'userinfo',
    name: 'userinfo',
    component: () => import('../views/UserInfo.vue')
  }
}

// 傳入后臺數(shù)據(jù) 生成路由表
menusToRoutes(menusData)

// 將菜單信息轉(zhuǎn)成對應(yīng)的路由信息 動態(tài)添加
function menusToRoutes(data) {
  const result = []
  const children = []

  result.push({
    path: '/',
    component: () => import('../components/Index.vue'),
    children,
  })

  data.forEach(item => {
    generateRoutes(children, item)
  })

  children.push({
    path: 'error',
    name: 'error',
    component: () => import('../components/Error.vue')
  })

  // 最后添加404頁面 否則會在登陸成功后跳到404頁面
  result.push(
    {path: '*', redirect: '/error'},
  )

  return result
}

function generateRoutes(children, item) {
  if (item.name) {
    children.push(asyncRoutes[item.name])
  } else if (item.children) {
    item.children.forEach(e => {
      generateRoutes(children, e)
    })
  }
}

所有的代碼實(shí)現(xiàn),我都放在 github 上,動態(tài)菜單的實(shí)現(xiàn)放在這個項目下的 src/components/Index.vue、src/permission.js 和 src/utils/index.js下

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI