Vue <script setup> - 如何处理多个动态组件?

lau*_*kok 5 vue.js vue-component vuejs3

似乎不可能将下面的 Options API 代码转换为<script setup>

    <template>
      <div>
        <component :is="layout">
          <router-view/>
        </component>
      </div>
    </template>
    
    <script>
    const defaultLayout = 'default'
    
    import Dark from './layouts/dark.vue'
    import Light from './layouts/light.vue'
    import Default from './layouts/default.vue'
    
    export default {
      name: 'App',
    
      components: {
        Dark,
        Light,
        Default
      },
    
      computed: {
        layout () {
          return (this.$route.meta.layout || defaultLayout)
        }
      }
    }
    </script>
Run Code Online (Sandbox Code Playgroud)

我的尝试:

    <script setup>
    import { computed } from 'vue'
    import { useRouter, useRoute } from 'vue-router'
    
    import Dark from './layouts/dark.vue'
    import Light from './layouts/light.vue'
    import Default from './layouts/default.vue'
    
    const router = useRouter()
    const route = useRoute()
    
    const defaultLayout = 'default'
    const layout = computed(() => route.meta.layout || defaultLayout )
    </script>
Run Code Online (Sandbox Code Playgroud)

结果:

没有加载选项的布局<script setup>,而只是加载<default><dark><light>块,例如:

    <div id="app">
    <default>
    ...
    ...
    </default>
    </div>
Run Code Online (Sandbox Code Playgroud)

根据这里的文档,我们可以使用三元:

    <component :is="someCondition ? Foo : Bar" />
Run Code Online (Sandbox Code Playgroud)

但这并不理想。因为您可能有两个以上的动态组件需要解决。我们不能让三元太长。我们可以吗?

有任何想法吗?

Ste*_* B. 13

The trick is to return the referenced variable rather than it's name.

    <script setup>
    import { computed } from 'vue'
    import { useRouter, useRoute } from 'vue-router'
    
    import Dark from './layouts/dark.vue'
    import Light from './layouts/light.vue'
    import Default from './layouts/default.vue'
    
    const router = useRouter()
    const route = useRoute()
    
    const layouts = {
      default: Default,
      light: Light,
      dark: Dark
    };
    
    const defaultLayout = 'default'
    const layout = computed(() => layouts[route.meta.layout || defaultLayout] )
    </script>
Run Code Online (Sandbox Code Playgroud)

Reason

While with options API components are registered locally and can be resolved by it's name (string key), with <script setup> the components are used directly without registration so it is not possible to use string key to resolve them...