Browse Source

!130 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题
Merge pull request !130 from 玲娜贝er/dev

疯狂的狮子Li 5 months ago
parent
commit
142effd4f2
2 changed files with 44 additions and 3 deletions
  1. 5 3
      src/store/modules/permission.ts
  2. 39 0
      src/utils/createCustomNameComponent.tsx

+ 5 - 3
src/store/modules/permission.ts

@@ -9,6 +9,8 @@ import Layout from '@/layout/index.vue';
 import ParentView from '@/components/ParentView/index.vue';
 import InnerLink from '@/layout/components/InnerLink/index.vue';
 
+import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
+
 // 匹配views里面所有的.vue文件
 const modules = import.meta.glob('./../../views/**/*.vue');
 export const usePermissionStore = defineStore('permission', () => {
@@ -82,7 +84,7 @@ export const usePermissionStore = defineStore('permission', () => {
       } else if (route.component?.toString() === 'InnerLink') {
         route.component = InnerLink;
       } else {
-        route.component = loadView(route.component);
+        route.component = loadView(route.component, route.name as string);
       }
       if (route.children != null && route.children && route.children.length) {
         route.children = filterAsyncRouter(route.children, route, type);
@@ -153,12 +155,12 @@ export const filterDynamicRoutes = (routes: RouteRecordRaw[]) => {
   return res;
 };
 
-export const loadView = (view: any) => {
+export const loadView = (view: any, name: string) => {
   let res;
   for (const path in modules) {
     const dir = path.split('views/')[1].split('.vue')[0];
     if (dir === view) {
-      res = () => modules[path]();
+      res = createCustomNameComponent(modules[path], { name });
     }
   }
   return res;

+ 39 - 0
src/utils/createCustomNameComponent.tsx

@@ -0,0 +1,39 @@
+/**
+ * 后台返回的路由动态生成name 解决缓存问题
+ * 感谢 @fourteendp
+ * 详见 https://github.com/vbenjs/vue-vben-admin/issues/3927
+ */
+import { Component, defineComponent, h } from 'vue';
+
+interface Options {
+  name?: string;
+}
+
+export function createCustomNameComponent(loader: () => Promise<any>, options: Options = {}): () => Promise<Component> {
+  const { name } = options;
+  let component: Component | null = null;
+
+  const load = async () => {
+    try {
+      const { default: loadedComponent } = await loader();
+      component = loadedComponent;
+    } catch (error) {
+      console.error(`Cannot resolve component ${name}, error:`, error);
+    }
+  };
+
+  return async () => {
+    if (!component) {
+      await load();
+    }
+
+    return Promise.resolve(
+      defineComponent({
+        name,
+        render() {
+          return h(component as Component);
+        }
+      })
+    );
+  };
+}