vue-element-admin 简单(无侵入)的多级路由 缓存 解决方案

ftf50wuq  于 2022-10-22  发布在  其他
关注(0)|答案(3)|浏览(704)

Feature request(新功能建议)

首先多级路由主要是为了生成菜单
Layout.vue 的 router-view 实现了缓存
那么模仿 Layout.vue 创建一个空 component : Empty.vue 用来无侵入地生成菜单
只有倒数第二级路由使用 Layout.vue,所以只会缓存最后一级路由的页面 component
至此缓存再也不受多级路由影响

图例

/三级路由                                                /二级路由
+-----------------------------------+                  +------------------------------+
| Empty.vue                         |                  | Layout.vue                   |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
| | Layout.vue                      |  +------------>  | | router-view              | |
| |     +-------------------------+ |                  | |                          | |
| |     |router-view              | |                  | |                          | |                           
| +-----+-------------------------+ |                  | +-----+--------------------+ |
+-----------------------------------+                  +------------------------------+

路由案例

{
    // 一级
    path: '/repair-maintenance',
    component: Empty,
    redirect: '/repair-maintenance/maintenance/workOrder',
    meta: { title: '维修/保养', icon: 'tree', roles: ['manager', 'worker'] },
    children: [
      // 三级模块
      repairRouter,
      maintenanceRouter,
      {
        // 二级
        path: 'calendar',
        component: Layout,
        children: [
          {
            // 三级
            path: 'calendar-plan',
            component: () => import('@/views/calendar-plan'),
            name: 'CalendarPlan',
            meta: { title: '计划日历', icon: 'el-icon-date' }
          }
        ]
      }
    ]
  },

空模板 Empty.vue

<template>
  <router-view />
</template>

<script>
export default {
  name: 'Empty'
}
</script>

完成以上虽然可以正常缓存,但整个 Layout 会被销毁并重建;
所以在 permission.js 的全局路由守卫中添加以下代码过滤掉 Empty.vue

// 过滤掉用于生成目录的空组件 Empty.vue
  const empty_list = to.matched.filter(item => item.components.default.name === 'Empty')
  empty_list.forEach(empty => {
    to.matched.splice(to.matched.findIndex(item => item.name === empty.name), 1)
  })

效果展示(数据库 id 作为 views 模块 name 报错)

后台生成的部分路由

{
"redirect": {
	"name": "161"
},
"path": "/maintenance-rr",
"component": "Empty",
"hidden": false,
"children": [
	{
		"redirect": {
			"name": "1611"
		},
		"path": "maintenance",
		"component": "Empty",
		"hidden": false,
		"children": [
			{
				"redirect": {
					"name": "16111"
				},
				"path": "plan",
				"component": "Layout",
				"hidden": false,
				"children": [
					{
						"path": "test",
						"component": "/test/test",
						"hidden": false,
						"children": [],
						"meta": {
							"icon": null,
							"opened": 1,
							"title": "页面"
						},
						"name": "16111"
					},
					{
						"path": "test2",
						"component": "/test/test2",
						"hidden": false,
						"children": [],
						"meta": {
							"icon": null,
							"opened": 1,
							"title": "页面2"
						},
						"name": "16112"
					}
				],
				"meta": {
					"icon": null,
					"opened": 1,
					"title": "三级目录"
				},
				"name": "1611"
			}
		],
		"meta": {
			"icon": null,
			"opened": 1,
			"title": "二级目录"
		},
		"name": "161"
	},
	{
		"path": "rr",
		"component": "Layout",
		"hidden": false,
		"children": [],
		"meta": {
			"icon": null,
			"opened": 1,
			"title": "二级目录2"
		},
		"name": "162"
	}
],
"meta": {
	"icon": null,
	"opened": 1,
	"title": "一级目录"
},
"name": "16"
}
xeufq47z

xeufq47z1#

是只是思路还是已经实践过确定可行,最好能提供个测试工程,这样大家可以本地部署测试下看看有没有其它bug

voj3qocg

voj3qocg3#

实测这个方案还是有弊端的,将 Layout 放在路由倒数第二级上,意味着可能会出现多个处于不同层级上的 Layout,而当不同层级之间的路由进行跳转时,整个 Layout 会被销毁并重建,例如:

{
    path: '/module1',
    component: Empty,
    children: [
        {
            path: 'xxx',
            component: Layout,
            children: [
                {
                    path: 'xxx',
                    component: import('1.vue')
                }
            ]
        },
        {
            path: 'yyy',
            component: Empty,
            children: [
                {
                    path: 'yyy',
                    component: Layout,
                    children: [
                        {
                            path: 'yyy',
                            component: import('2.vue')            
                        }
                    ]
                }
            ]
        }
    ]
}

相关问题