告别硬编码:vue-pure-admin动态路由传参与组件加载新方案
告别硬编码:vue-pure-admin动态路由传参与组件加载新方案
【免费下载链接】vue-pure-admin 项目地址: https://gitcode.com/gh_mirrors/vue/vue-pure-admin
你是否还在为Vue项目中路由传参的繁琐配置而困扰?是否遇到过路由组件路径硬编码导致的维护难题?本文将带你探索vue-pure-admin中基于component路径动态加载的路由传参新方式,让你的路由管理更灵活、更高效。读完本文,你将掌握动态路由配置、组件路径解析和权限控制的实战技巧,轻松应对复杂项目的路由管理需求。
传统路由传参的痛点与挑战
在传统的Vue项目开发中,路由配置往往采用静态方式,组件路径通过字符串硬编码到路由定义中。这种方式在小型项目中或许可行,但随着项目规模扩大,会带来诸多问题:
- 维护成本高:当组件路径发生变化时,需要手动修改所有相关的路由配置
- 扩展性差:新增页面或修改路由结构时,需重启开发服务才能生效
- 权限控制复杂:不同角色需要不同路由权限时,难以实现动态适配
vue-pure-admin作为一款优秀的Vue3后台管理系统模板,提供了一套优雅的解决方案。通过分析src/router/index.ts和src/router/utils.ts的源码实现,我们可以发现其独特的动态路由处理机制。
动态路由加载的核心实现
vue-pure-admin的动态路由加载机制主要依赖于两个关键函数:formatTwoStageRoutes和formatFlatteningRoutes。这两个函数在src/router/utils.ts中定义,负责将多层嵌套路由转换为适合Vue Router处理的格式。
/**
* 一维数组处理成多级嵌套数组(三级及以上的路由全部拍成二级,keep-alive 只支持到二级缓存)
* https://github.com/pure-admin/vue-pure-admin/issues/67
* @param routesList 处理后的一维路由菜单数组
* @returns 返回将一维数组重新处理成规定路由的格式
*/
function formatTwoStageRoutes(routesList: RouteRecordRaw[]) {
if (routesList.length === 0) return routesList;
const newRoutesList: RouteRecordRaw[] = [];
routesList.forEach((v: RouteRecordRaw) => {
if (v.path === "/") {
newRoutesList.push({
component: v.component,
name: v.name,
path: v.path,
redirect: v.redirect,
meta: v.meta,
children: []
});
} else {
newRoutesList[0]?.children.push({ ...v });
}
});
return newRoutesList;
}
路由组件的动态导入
在vue-pure-admin中,路由组件的动态导入通过addAsyncRoutes函数实现。该函数会根据后端返回的路由配置,自动匹配并导入对应的组件文件:
function addAsyncRoutes(arrRoutes: Array<RouteRecordRaw>) {
if (!arrRoutes || !arrRoutes.length) return;
const modulesRoutesKeys = Object.keys(modulesRoutes);
arrRoutes.forEach((v: RouteRecordRaw) => {
// 将backstage属性加入meta,标识此路由为后端返回路由
v.meta.backstage = true;
if (v.meta?.frameSrc) {
v.component = IFrame;
} else {
// 对后端传component组件路径和不传做兼容
const index = v?.component
? modulesRoutesKeys.findIndex(ev => ev.includes(v.component as any))
: modulesRoutesKeys.findIndex(ev => ev.includes(v.path));
v.component = modulesRoutes[modulesRoutesKeys[index]];
}
if (v?.children && v.children.length) {
addAsyncRoutes(v.children);
}
});
return arrRoutes;
}
这种方式使得路由配置与组件实现解耦,极大提高了系统的灵活性和可维护性。
component路径动态加载的实战应用
在实际开发中,component路径动态加载可以应用于多种场景,如标签页切换、动态表单等。以下是几个典型的应用示例:
1. 标签页组件动态切换
在src/views/account-settings/index.vue中,通过动态加载不同的组件实现标签页内容切换:
<template>
<div class="account-settings">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="个人资料" name="Profile">
<component :is="currentComponent" />
</el-tab-pane>
<!-- 其他标签页 -->
</el-tabs>
</div>
</template>
<script setup lang="ts">
import Profile from "./components/profile.vue";
import Preferences from "./components/preferences.vue";
import SecurityLog from "./components/security-log.vue";
import AccountManagement from "./components/account-management.vue";
const components = [
{ name: "Profile", component: Profile },
{ name: "Preferences", component: Preferences },
{ name: "SecurityLog", component: SecurityLog },
{ name: "AccountManagement", component: AccountManagement }
];
const activeName = ref("Profile");
const currentComponent = computed(() => {
return components.find(c => c.name === activeName.value)?.component;
});
</script>
2. 动态表单组件加载
在src/views/schema-form/index.vue中,通过动态组件实现不同表单类型的切换:
<template>
<div class="schema-form">
<el-radio-group v-model="selected" @change="handleChange">
<el-radio-button :label="0">基础表单</el-radio-button>
<el-radio-button :label="1">高级表单</el-radio-button>
</el-radio-group>
<component :is="currentComponent" />
</div>
</template>
<script setup lang="ts">
import BasicForm from "./components/basic-form.vue";
import AdvancedForm from "./components/advanced-form.vue";
const selected = ref(0);
const components = [
{ component: BasicForm },
{ component: AdvancedForm }
];
const currentComponent = computed(() => {
return components[selected.value].component;
});
</script>
3. 表格行内编辑组件
在src/views/table/edit.vue中,动态加载不同类型的编辑组件:
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="姓名" width="180" />
<el-table-column prop="age" label="年龄" width="180" />
<el-table-column label="操作">
<template #default="scope">
<el-button @click="handleEdit(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="dialogVisible" title="编辑">
<component :is="currentComponent" :form-data="formData" />
</el-dialog>
</template>
<script setup lang="ts">
import TextEditor from "./components/text-editor.vue";
import NumberEditor from "./components/number-editor.vue";
import SelectEditor from "./components/select-editor.vue";
const dialogVisible = ref(false);
const formData = ref({});
const currentComponent = ref(null);
const handleEdit = (row) => {
formData.value = { ...row };
dialogVisible.value = true;
// 根据不同类型加载不同编辑器
if (row.type === 'text') {
currentComponent.value = TextEditor;
} else if (row.type === 'number') {
currentComponent.value = NumberEditor;
} else {
currentComponent.value = SelectEditor;
}
};
</script>
动态路由与权限控制的结合
在企业级应用中,动态路由往往需要与权限控制相结合。vue-pure-admin通过src/router/utils.ts中的filterNoPermissionTree函数实现了基于角色的路由过滤:
/** 从localStorage里取出当前登录用户的角色roles,过滤无权限的菜单 */
function filterNoPermissionTree(data: RouteComponent[]) {
const currentRoles =
storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? [];
const newTree = cloneDeep(data).filter((v: any) =>
isOneOfArray(v.meta?.roles, currentRoles)
);
newTree.forEach(
(v: any) => v.children && (v.children = filterNoPermissionTree(v.children))
);
return filterChildrenTree(newTree);
}
这种方式确保了用户只能访问其权限范围内的路由和组件,提高了系统的安全性。
总结与展望
vue-pure-admin的component路径动态加载方案为Vue项目提供了更灵活、更高效的路由管理方式。通过将路由配置与组件实现解耦,不仅降低了维护成本,还大大提高了系统的扩展性和安全性。
未来,随着Web Components标准的普及,我们可以期待更加灵活的组件加载方式。同时,结合微前端架构,动态路由加载机制将在大型应用中发挥更大的作用。
如果你觉得本文对你有帮助,请点赞、收藏并关注我们,获取更多关于vue-pure-admin的实用技巧和最佳实践。下一期我们将探讨"动态路由的性能优化策略",敬请期待!
【免费下载链接】vue-pure-admin 项目地址: https://gitcode.com/gh_mirrors/vue/vue-pure-admin
更多推荐

所有评论(0)