在动态路由中绑定多实例组件
最近在开发中遇上了一个问题,我们有十几个上传的页面,功能几乎一致,只有内部的文本和一个日期选择器不一样,但是BA又希望可以通过url访问到每个页面,技术上又不希望真的去写十几个一样的页面——这也太蠢了。于是就想到了通过一份配置文件,提供一个页面信息的list,然后遍历这个list,动态生成route信息和组件,并添加到路由中:
配置列表:
const pages: Page[] = [
{
title: 'AAA',
url: '/home/aaa',
},
{
title: 'BBB',
url: '/home/bbb',
},
...
]
配置列表转换成路由信息:
const list = pages.map((page) => {
return {
path: page.url,
name: page.title,
component: () => import('@/components/TestPage.vue'),
meta: { data: page }
};
});
添加路由信息:
const routes = [
{
path: '/',
redirect: '/home',
component: () => import('@/pages/IndexPage.vue'),
children: [
{
path: '/home',
name: 'Home',
component: () => import('@/pages/Home.vue'),
children: [
{
// other route info
},
...list // 把生成的路由信息添加到子路由里
]
},
...
]
}
];
Home中添加动态路由
<template>
<router-view />
</template>
但是这样有一个问题,如果在aaa页面上修改了某个值,那么在bbb上这个值也会跟着被修改,这是因为pages中定义的所有路由,绑定的其实是同一个组件实例。为了解决这个问题,一个简单的解决方法就是把组件由单例的,改为多实例的,即每个url都绑定一个自己的组件实例。
首先需要修改动态生成的路由信息,增加key,强制vue-router为每个不同的路由配置创建一个新的组件实例:
const list = pages.map((page) => {
return {
...
meta: { data: page },
key: page.title
};
});
同时,还要修改Home,来应用key
<template>
<router-view v-slot="{ Component, route }">
<keep-alive>
<Component :is="Component" :key="route.name" />
</keep-alive>
</router-view>
</template>
这样,每个url都有一个自己的组件实例,防止互相之间修改数据。这个解决方法并不算很好,如果列表里的信息很多,会生成很多组件,对性能产生影响