может кто-нибудь помочь мне с созданием динамического компонента на основе данных JSON в NUXT3.
У меня есть компонент тела DataTable следующим образом:
<tbody class = "divide-y divide-gray-200">
<tr v-for = "item in data" :key = "item._id">
<td v-for = "column in columns" class = "whitespace-nowrap px-3 py-4 text-sm text-gray-500">
<div v-if = "column.definition">
<component :is = "resolveComponent(column?.definition(item[column.key]).component)" v-bind = "column?.definition(item[column.key]).component.props" >
{{ column?.definition(item[column.key]).slot }}
</component>
</div>
<div v-else>{{ item[column.key] }}</div>
</td>
</tr>
</tbody>
Как вы можете видеть, я хочу визуализировать компонент, в котором свойство :is
определено в column?.definition(item[column.key]).component
.
Функция определения возвращает объект, а свойство .comComponent содержит простую строку, как вы можете видеть здесь.
{title: 'Email', key: 'email', definition: (item)=>{return {component: 'GeneralButton', props: {to: item._id}, slot: item}}}
Итак, результат в этом примере, который должен быть отображен, на самом деле:
<component :is = "resolveComponent('GeneralButton')" ... >
И в этом проблема: компонентsolveComponent не работает, пока я передаю в него переменную. Если я передаю туда ту же строку, которая возвращается функцией определения, она отлично работает.
Я пробовал другие варианты, но ни один из них не сработал. Чаще всего используется глобальный компонент, поэтому GeneralButton должен быть глобальным. Этот подход работает, но я хочу создать полностью настраиваемый компонент и на самом деле не знаю, какой компонент я захочу использовать в будущем, поэтому для меня это не лучшее решение. (Я также видел совет установить все компоненты как глобальные, и я хочу избежать этой причины проблем с производительностью).
Другой подход заключался в том, чтобы переопределить автоматический импорт Nuxt3 и импортировать нужный компонент вручную в компонент DataTableBody. Это тоже работает, и функция resolveComponent()
работает с varibale :is
, но у нее та же проблема, что и у предыдущей: я не знаю, какой компонент я получу в функции Definition(). На самом деле это должно работать, если бы был способ динамически определить импорт на основе переменной, но я совершенно уверен, что это невозможно, что-то вроде:
import {`$componentToRender`} from '#components' //This does not work and I didnt find any solution which works
Есть ли на самом деле способ сделать это? Спасибо :)
Вы не можете передать переменную методуsolveComponent().
<template>
<component :is = "resolveComponent(aVariableThatHoldsComponentName)" />
This is Not OK ❌
<component :is = "resolveComponent('MyComponent')" />
This is OK ✅
<component :is = "conditionalComponent" />
This is OK ✅
<component :is = "getComponent(key)" />
This is OK ✅
</template>
<script setup>
const aVariableThatHoldsComponentName = 'MyComponent';
const conditionalComponent = computed(() => {
return condition ? resolveComponent('ComponentA') : resolveComponent('ComponentB')
})
const componentMap = {
key1: resolveComponent('MyComponentA'),
key2: resolveComponent('MyComponentB'),
key3: resolveComponent('MyComponentC'),
}
const getComponent = (key) => {
return componentMap[key]
}
const key = "key2";
</script>
Однако, если ваш компонент является глобальным (например: ~/comComponents/global/MyComponentName.vue или ~/comComponents/MyComponent.global.vue), вы можете использовать его следующим образом:
<template>
<component :is = "aVariableThatHoldsComponentName" />
This is OK ✅
</template>
Обратите внимание: глобальные компоненты следует использовать только в том случае, если вы уверены, что это необходимо, поскольку глобальные компоненты импортируются на каждую страницу, даже если они не используются.
@ Bartas139 Действительно, сделать компонент динамическим не так-то просто, и вот почему: Nuxt буквально сканирует ваше приложение и автоматически импортирует каждый компонент, необходимый для рендеринга каждой страницы, это делает возможным автоимпорт и делает ваше приложение аккуратным ( вытрясти неиспользуемые компоненты). Когда <Component> найден, Nuxt должен знать, какие компоненты необходимо включить в ваше приложение, чтобы его можно было условно импортировать (в зависимости от логики вашего приложения). Но опять же, если набор ваших компонентов является динамическим, вы всегда можете поместить их в /comComponents/global.
Привет, спасибо за ответ. Все эти подходы требуют знать, какой компонент я хочу визуализировать, потому что мне нужно передать литеральную строку вsolveComponent, или мне нужно определить объект компонентов, или мне нужно знать, какой компонент я должен сделать глобальным. На данный момент я не нашел другого решения, которое должно было бы быть полностью динамичным. На самом деле я упускаю из виду суть разрешения компонента + <компонент>, потому что вам всегда нужно знать и иметь жестко закодированную строку желаемого компонента, и в этом случае я на самом деле не вижу в этом пользы, есть лучшие способы справиться с набором известных компонентов. компоненты.