I'm trying to loop over a list of component described by strings (I get the name of the component from another , like const componentTreeName = ["CompA", "CompA"]
.
My code is a simple as:
<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>
EDIT
I tried this with not much success.
CodePudding user response:
When using script setup
, you need to reference the component and not the name or key.
To get it to work, I would use an object where the string can be used as a key to target the component from an object like this:
<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>
To use a global component, you could assign components by pulling them from the app context. But this would require the app
context to be available and the keys known.
example:
import { app } from '../MyApp.js'
const components = {
CompA: app.component('CompA')
}
I haven't tested this, but this might be worth a try to check with getCurrentInstance
import { ref,getCurrentInstance } from 'vue'
const components = getCurrentInstance().appContext.components;
CodePudding user response:
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>
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>
Note: markRaw
is used on the component definition because no reactivity is needed on it.