动态路由深度克隆路由导致VueRouter component重载

今天在一个以 vue-element-admin 为框架的项目中遇到这样一个问题:固定路由与动态路由切换时,vue 会重新加载 Layout 组件。

后经过排查,发现是由于在进行动态路由添加时,使用了 lodash 的 cloneDeep() 对原来的路由进行克隆导致的。

路由配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import Layout from '@/layout'

// 固定路由
export const constantRoutes = [
...
{
path: '/',
component: Layout,
redirect: '/dashboard',
name: 'DashboardIndex',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},
]

// 动态路由
export const asyncRoutes = [
{
path: '/workflow',
name: 'workflow',
component: Layout,
meta: {
title: '工作流程',
icon: 'workflow',
functionCode: 'router/workflow'
},
redirect: '/workflow/ownWorkflow/searchWorkflow',
children: [
{
path: 'createWorkflow',
component: () => import('@/views/workflow/own-workflow/create-workflow'),
name: 'CreateWorkFlow',
meta: {
title: '新建工作',
icon: 'add-document',
functionCode: 'router/createWorkflow',
noCache: true
}
},
]
}
]

动态路由生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store中生成路由
generateRoutes({ commit }, access) {
return new Promise(resolve => {
let accessedRoutes
if (access.includes('*')) {
const cloneDatas = _.cloneDeep(asyncRoutes)
accessedRoutes = cloneDatas
} else {
accessedRoutes = filterAsyncRoutes(asyncRoutes, access)
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}

原理分析 为什么使用 clone 后的路由配置,在切换时就会重新加载路由里面的 component 组件呢? 原来是因为 cloneDeep() 会进行深度克隆,路由中的 component 也会变成新的对象,该对象与固定路由中的 component 不是同一个,所以两者在进行切换时,会重载 Layout 布局。