vue路由组件路径如何用变量形式动态引入
作者:Dreams゜
vue路由组件路径用变量形式动态引入
router.js路由配置文件
import Router from 'vue-router' const createRouter = ()=> new Router({ mode: 'history', routes: [] }) const router = createRouter() // 在路由上加一个全局方法,用于动态添加路由 router.$addRouterPlus = (params)=>{ router.matcher = new Router({mode: 'history'}).matcher const rList = [...params] router.addRoutes(rList) } return router
用变量的形式引入组件
- require:可以正常引入
- import:用这个引入我这边是没有生效的,网上查资料有说是路径用全变量形式识别不了,但我加上一段固定路径也不生效(@/views/${path})
const path= 'views/projectManage/projectInfo.vue'//文件路径 const menuPathList = [{ path: '/project', // component: () => import(`@/${path}`) component: (resolve)=>require([`@/${path}`], resolve) }] // 更新路由配置 this.$router.$addRouterPlus(this.menuPathList)
vue动态路由导入
静态路由的回顾
1.创建router/index.js文件,这里只有一些简单的页面
import Vue from 'vue' import Router from 'vue-router' import Login from '@/view/login/Login' import Index from '@/layout/Index' import Welcome from '@/layout/welcome/Welcome' Vue.use(Router) export default new Router({ routes: [ { path: '/login', name: 'Login', component: Login }, { path: '/', component: Index, redirect: '/welcome', meta: {requireAuth: true}, children: [ { path: '/welcome', component: Welcome, name: '首页', meta: {title: '首页', requireAuth: true} } ] } ] })
2.创建router/permission.js文件,配置导航守卫,可以在每次路由跳转前做一些操作,待会获取动态路由操作也在这里配置
import router from '@/router/index' import 'element-ui/lib/theme-chalk/index.css' import '@fortawesome/fontawesome-free/css/all.min.css' import NProgress from 'nprogress' import 'nprogress/nprogress.css' NProgress.configure({ easing: 'ease', // 动画方式 speed: 500, // 递增进度条的速度 showSpinner: false, // 是否显示加载ico trickleSpeed: 200, // 自动递增间隔 minimum: 0.3 // 初始化时的最小百分比 }) // 白名单 const whiteList = ['/login'] // no redirect whitelist // 导航守卫 router.beforeEach((to, from, next) => { NProgress.start() if (to.meta.requireAuth) { // 判断该路由是否需要登录权限 if (sessionStorage.getItem('loginName') !== null) { // 判断本地是否存在token next() // 这里是待会获取异步路由的地方 } else { // 未登录,跳转到登陆页面 next({ path: '/login' }) } } else { if (whiteList.indexOf(to.path) !== -1) { next() } else { if (sessionStorage.getItem('loginName') !== null) { // 判断本地是否存在token next(`/?redirect=${to.path}`) } else { next(`/login?redirect=${to.path}`) } } } }) router.afterEach(() => { // 在即将进入新的页面组件前,关闭掉进度条 NProgress.done() })
3.在main.js里引入刚才创建的router下的index.js文件和permission.js文件,如下
import router from '@/router' import './router/permission' new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' })
4.在App入口中放入路由跳转的视图区,跳转的路由页面都显示在这里
<div id="app"> <router-view /> </div>
现在静态路由就配好了,可以正常的跳转了!
1.首先呢,router/index.js,没有什么需要改的,把你需要动态获取的路由信息删除掉即可,可以留一部分静态路由,如登录页,首页等等,若全删,routes赋为[]即可。
2.创建一个文件,我命名为getAsyncRouter.js,用来处理获取到的动态路由信息。
// 用于处理动态菜单数据,将其转为 route 形式 export function fnAddDynamicMenuRoutes (menuList = [], routes = []) { // 用于保存普通路由数据 let temp = [] // 用于保存存在子路由的路由数据 let route = [] // 遍历数据 for (let i = 0; i < menuList.length; i++) { // 存在子路由,则递归遍历,并返回数据作为 children 保存 if (menuList[i].children && menuList[i].children.length > 0) { // 获取路由的基本格式 route = getRoute(menuList[i]) // 递归处理子路由数据,并返回,将其作为路由的 children 保存 route.children = fnAddDynamicMenuRoutes(menuList[i].children) // 保存存在子路由的路由 routes.push(route) } else { // 保存普通路由 temp.push(getRoute(menuList[i])) } } // 返回路由结果 return routes.concat(temp) } // 返回路由的基本格式 function getRoute (item) { // 路由基本格式 let route = { // 路由的路径 path: item.url, // 路由名 name: item.name, // 路由所在组件 // component: (resolve) => require([`@/layout/Index`], resolve), component: (resolve) => require([`@/view${item.curl}`], resolve), meta: { id: item.id, icon: item.icon }, // 路由的子路由 children: [] } // 返回 route return route }
这里是两个函数,把获取到的数据处理成路由表数据,将其变化成 route 的形式。
fnAddDynamicMenuRoutes 用于递归菜单数据。
getRoute 用于返回某个数据转换的 路由格式。
注释写的应该算是很详细了,主要讲一下思路:
对数据进行遍历, 定义两个数组(temp,route),temp用于保存没有子路由的路由,route 用于保存存在子路由的路由。
如果某个数据存在子路由,则对子路由进行遍历,并将其返回结果作为当前数据的 children。并使用 route 保存路由。
如果某个数据不存在子路由,则直接使用 temp 保存路由。
最后,返回两者拼接的结果,即为转换后的数据。
route 格式一般如下:
path
:指路由路径(可以根据路径定位路由)。name
:指路由名(可以根据路由名定位路由)。component
:指路由所在的组件。children
:指的是路由组件中嵌套的子路由。meta
:用于定义路由的一些元信息。
这里有个大坑!!! 在配置component的时候,需要动态导入组件,也就是vue异步组件
综上所述,就是说,组件的导入可以使用字符串拼接的方式导入,可以使用模板字符串导入(字符串中含有变量),但是使用模板字符串导入时不能够只使用变量!!必须指定一个目录,不能全用变量代替!
3.有了处理动态路由数据的函数,那就需要在合适的地方调用,以发挥作用。这时就需要用到beforeEach了,在router/permission.js文件,配置导航守卫,可以在每次路由跳转前做一些操作,这里就是获取动态路由了
import router from '@/router/index' import 'element-ui/lib/theme-chalk/index.css' import '@fortawesome/fontawesome-free/css/all.min.css' import NProgress from 'nprogress' import 'nprogress/nprogress.css' import {fnAddDynamicMenuRoutes} from '@/router/getAsyncRouter' import {getRouter} from '@/api/sys/Menu' import store from '@/store' NProgress.configure({ easing: 'ease', // 动画方式 speed: 500, // 递增进度条的速度 showSpinner: false, // 是否显示加载ico trickleSpeed: 200, // 自动递增间隔 minimum: 0.3 // 初始化时的最小百分比 }) // 白名单 const whiteList = ['/login'] // no redirect whitelist // 导航守卫 router.beforeEach((to, from, next) => { NProgress.start() try { // 判断是否已经获取过动态菜单,未获取,则需要获取一次 if (store.getters.dynamicRoutes.length === 0) { if (whiteList.indexOf(to.path) !== -1) { next() } else { getRouter().then(res => { if (res.code === 0) { let menuRouter = fnAddDynamicMenuRoutes(res.data[0].children) store.dispatch('app/dynamicRoutes', menuRouter).then(() => { router.addRoutes(store.getters.dynamicRoutes) next({...to, replace: true}) }) } else { console.log('获取动态路由失败!') next({path: '/login'}) } }) } } else { // 路由已存在或已缓存路由 if (to.meta.requireAuth) { if (sessionStorage.getItem('loginName') !== null) { // 判断本地是否存在token next() } else { // 未登录,跳转到登陆页面 next({path: '/login'}) } } else { if (whiteList.indexOf(to.path) !== -1) { next() } else { if (sessionStorage.getItem('loginName') !== null) { // 判断本地是否存在token next(`/?redirect=${to.path}`) } else { next(`/login?redirect=${to.path}`) } } } } } catch (error) { console.log('出错了') next(`/login?redirect=${to.path}`) } }) router.afterEach(() => { // 在即将进入新的页面组件前,关闭掉进度条 NProgress.done() })
4.接下来看一看,store的写法
const state = { dynamicRoutes: [] } const mutations = { DYNAMIC_ROUTES (state, routes) { state.dynamicRoutes = routes } } const actions = { dynamicRoutes ({commit}, routes) { commit('DYNAMIC_ROUTES', routes) } }
在刷新页面时遇到一个问题,动态路由表会随着vuex的刷新而消失。
处理:这里在app.vue页面刷新时利用sessionStorage存储一下store,防止刷新丢失vuex。
export default { name: 'App', created () { // 在页面加载时读取sessionStorage里的状态信息 if (sessionStorage.getItem('storeData')) { this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('storeData')))) } // 在页面刷新时将vuex里的信息保存到sessionStorage里 window.addEventListener('beforeunload', () => { sessionStorage.setItem('storeData', JSON.stringify(this.$store.state)) }) // 兼容iphone手机 window.addEventListener('pagehide', () => { sessionStorage.setItem('storeData', JSON.stringify(this.$store.state)) }) } }
//登录的时候也调用一下 getRouter().then(res => { if (res.code === 0) { let menuRouter = fnAddDynamicMenuRoutes(res.data[0].children) store.dispatch('app/dynamicRoutes', menuRouter).then(() => { router.addRoutes(store.getters.dynamicRoutes) }) console.log(store.getters.dynamicRoutes) } else { console.log('获取动态路由失败!') router.push('/login') } })
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。