Vue 3:for 循环中的组件 `:is` 失败

tob*_*ora 2 vue.js vuejs3

我正在尝试循环遍历由字符串描述的组件列表(我从另一个 获取组件的名称,例如const componentTreeName = ["CompA", "CompA"].

我的代码很简单:

<script setup>
    import CompA from './CompA.vue'
    import { ref } from 'vue'

    // I do NOT want to use [CompA, CompA] because my inputs are strings
    const componentTreeName = ["CompA", "CompA"]
</script>

<template>
  <h1>Demo</h1>
  <template v-for="compName in componentTreeName">
    <component :is="compName"></component>
  </template>
</template>
Run Code Online (Sandbox Code Playgroud)

演示在这里

编辑

我尝试但没有取得多大成功。

Dan*_*iel 5

使用时script setup,您需要引用组件而不是名称或键。

为了让它工作,我将使用一个对象,其中字符串可以用作从对象中定位组件的键,如下所示:

<script setup>
    import CompA from './CompA.vue'
    import { ref } from 'vue'
    const components = {CompA};

    // I do NOT want to use [CompA, CompA] because my inputs are strings
    const componentTreeName = ["CompA", "CompA"]
</script>

<template>
  <h1>Demo</h1>
  <template v-for="compName in componentTreeName">
    <component :is="components[compName]"></component>
  </template>
</template>
Run Code Online (Sandbox Code Playgroud)

要使用全局组件,您可以通过从应用程序上下文中提取组件来分配组件。但这需要app上下文可用并且密钥已知。

例子:

import { app } from '../MyApp.js'
const components = {
  CompA: app.component('CompA')
}
Run Code Online (Sandbox Code Playgroud)

我还没有测试过这个,但这可能值得一试getCurrentInstance

import { ref,getCurrentInstance } from 'vue'
const components = getCurrentInstance().appContext.components;
Run Code Online (Sandbox Code Playgroud)


ton*_*y19 5

Use resolveComponent() on the component name to look up the global component by name:

<script setup>
import { resolveComponent, markRaw } from 'vue'
const myGlobalComp = markRaw(resolveComponent('my-global-component'))
</script>

<template>
  <component :is="myGlobalComp" />
<template>
Run Code Online (Sandbox Code Playgroud)

demo 1

If you have a mix of locally and globally registered components, you can use a lookup for local components, and fall back to resolveComponent() for globals:

<script setup>
import LocalComponentA from '@/components/LocalComponentA.vue'
import LocalComponentB from '@/components/LocalComponentB.vue'
import { resolveComponent, markRaw } from 'vue'

const localComponents = {
  LocalComponentA,
  LocalComponentB,
}

const lookupComponent = name => {
  const c = localComponents[name] ?? resolveComponent(name)
  return markRaw(c)
}

const componentList = [
  'GlobalComponentA',
  'GlobalComponentB',
  'LocalComponentA',
  'LocalComponentB',
].map(lookupComponent)
</script>

<template>
  <component :is="c" v-for="c in componentList" />
</template>
Run Code Online (Sandbox Code Playgroud)

demo 2

Note: markRaw is used on the component definition because no reactivity is needed on it.