0

嗨 Vue 爱好者们,我一直在开发一个多租户应用程序,但遇到了动态布局问题。

要求:从公共文件夹加载特定于租户的 layout.vue 文件并环绕<router-view>它。

尝试了一些类似dynamic imports的东西,defineAsyncComponent但无法让它工作。

   // router:
        import store from '../store/index';
        import NestedApp from '../views/NestedApp.vue';
        // const layoutA = () => defineAsyncComponent(import(store.getters.pageLayout('LayoutA')));

        const routes = [
          {
            path: '/:tenant:/:locale',
            name: 'NestedApp',
            component: NestedApp,
            children: [
             {
                path: 'about',
                name: 'About',
                component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
                meta: { layout: () => import(store.getters.pageLayout('LayoutA')) }
              }
            ]
        ]


    // NestedApp.vue:
    <template>
      <div class="NestedApp">
        <navbar/>
        <component :is="layoutWrapper">
          <router-view/>
        </component>
      </div>
    </template>
    <script>
    import Navbar from '../components/Navbar.vue';
    export default {
      name: 'NestedApp',
      components: {
        Navbar,
      },
      computed: {
        layoutWrapper() {
          console.info(`layout: ${this.$route.meta.layout}`);
          return this.$route.meta.layout || 'div';
        }
      }
    }
    
    // LayoutA.vue:
    <template>
      <div class="LayoutA">
          <span>Layout A</span>
          <slot/>
      </div>
  </template>
   

我在浏览器控制台中收到以下错误: 在此处输入图像描述

4

1 回答 1

0

有一个解决这个问题的方法。从后端 API 调用通过模板字符串发送组件,然后通过 defineComponent 和 markRaw 方法从中创建一个组件。

API 响应:

"Layouts": {
        "LayoutA": {
            "name": "LayoutAbout",
            "template": "<div class='LayoutA' style='background-color: darkgray'><span>Layout A</span><slot/></div>"
        }
},

然后在 App.vue 中使用:

    import { defineComponent, markRaw } from 'vue';

    export default {
      name: 'App',
      methods: {
        loadLayout(pageLayout) {
          const layout = this.$store.getters.pageLayout(pageLayout);

          this.layoutWrapper = layout ? defineComponent(markRaw({...layout})) : 'div'; 
        }
      },
    created() {
      this.loadLayout(this.$route.meta.layout);
    },
    beforeRouteUpdate(to) {
      this.loadLayout(to.meta.layout);
    },
}
<template>
  <div class="App">
    <navbar/>
    <component :is="layoutWrapper">
      <router-view/>
    </component>
  </div>
</template>

于 2021-09-03T11:19:01.687 回答