动态路由和菜单

接口返回数据整理成动态路由

后端接口返回数据

{
  "code": 20000,
  "value": [
    {
      "path": "/example",
      "component": "layout/index.vue",
      "redirect": "/example/table",
      "name": "Example",
      "meta": { "title": "Example", "icon": "el-icon-s-help" },
      "children": [
        {
          "path": "table",
          "name": "Table",
          "component": "views/table/index.vue",
          "meta": { "title": "Table", "icon": "table" }
        },
        {
          "path": "tree",
          "name": "Tree",
          "component": "views/tree/index.vue",
          "meta": { "title": "Tree", "icon": "tree" }
        }
      ]
    }
  ]
}

整理数据

1.不用import的原因是webpack4X,import不能使用变量(有时候多几层字符串拼接也可以eg: '@/views/ x x x . v u e ′ ),所以这里使用 ( r e s o l v e ) = > r e q u i r e ( [ ‘ @ / {xxx}.vue'),所以这里使用(resolve) => require([`@/ xxx.vue),所以这里使用(resolve)=>require([‘@/{component}`], resolve) 处理接口返回的component
2.require和import区别

  • 语法:
    -使用(resolve) => require([@/views/${view}], resolve)是使用require语法来动态加载组件,而import ( )是ES6的模块导入语法。

  • 动态加载:
    -(resolve) => require([@/views/${view}], resolve)可以在运行时动态加载组件,而import ( )只能在编译时静态导入组件

  • 异步加载:
    -(resolve) => require([@/views/${view}], resolve)可以实现异步加载组件,只有在需要时才会加载对应的组件文件:只有访问这个路由网址时才会加载这个js。而import ( )会在编译时将所有导入的组件一起打包,无法实现异步加载,当项目打包时路由里的所有component都会打包在一个js 中,造成进入首页时,需要加载的内容过多,时间相对比较长

  • 代码分割:
    -(resolve) => require([@/views/${view}], resolve)可以实现代码分割,将不同的组件打包成不同的文件,按需加载。而import ( )会将所有导入的组件打包到一个文件中。你可以打包的时候看看目录结构就明白了。

综上所述:使用(resolve) => require([@/views/${view}], resolve)拼接component可以实现动态、异步加载和代码分割等功能,适用于需要按需加载和优化性能的场景。而import ( )适用于静态导入和编译时打包的场景。

function loadView(component) {
  return (resolve) => require([`@/${component}`], resolve)
}

// 处理动态路由
export function formatRoutes(menu) {
  const router = []
  menu.forEach(menuItem => {
    if (!validateNull(menuItem.component)) {
      const routerItem = {
        ...menuItem,
        component: loadView(menuItem.component),
        children: validateNull(menuItem.children) ? [] : formatRoutes(menuItem.children),
      }
      router.push(routerItem)
    }
  })
  return router
}

想要左侧菜单使用router.addRoutes()之后的全部路由,发现如下问题

  • 当router.addRoutes()之后打印router.options.routes打印出来的并不是全量的路由,仍然只有基本路由(虽然打印不出来,但是不影响使用,页面跳转没有任何问题)----只给matcher对象增加了新路由,并没有更新router.option,matcher对象是给vue-router内部使用的,所以项目里页面跳转没有出问题,但router.option打印不出来
  • 调用getRoutes报错----3.5.4版本的源码,发现vue官方新增了getRoutes方法,用于获取matcher对象上的全量路由
    解决方案: 使用状态管理工具,自行保存一份路由数据
    store/modules/menu.js

import { constantRoutes, lastRoutes } from '@/router'
import { getMenu } from '@/api/systemManage'

const state = {
  menu: constantRoutes
}

const mutations = {
  SET_MENU: (state, dynamicMenu) => {
    state.menu = constantRoutes.concat(dynamicMenu, lastRoutes)
  }
}

const actions = {
  // get menu
  GetMenu({ commit, state }) {
    return new Promise((resolve, reject) => {
      getMenu().then(res => {
        const dynamicMenu = res.value || []
        commit('SET_MENU', dynamicMenu)
        resolve(dynamicMenu)
      }).catch(error => {
        reject(error)
      })
    })
  }
}

export default {
  namespaced: true, // 模块的上下文局部化,使其成为带命名空间的模块,模块的 getter、action 和 mutation 会带上模块的路径作为前缀,使用时需要指定完整路径。
  state,
  mutations,
  actions
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值