Nuxt3动态<component>

问题描述 投票:0回答:1

有人可以帮我创建一个基于 NUXT3 中的 JSON 数据的动态组件吗?

我有这样的 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

中定义

定义函数返回一个对象,.component 属性包含一个简单的字符串,如下所示

{title: 'Email', key: 'email', definition: (item)=>{return {component: 'GeneralButton', props: {to: item._id}, slot: item}}}

所以这个例子中应该渲染的结果实际上是:

<component :is="resolveComponent('GeneralButton')" ... >

这就是问题所在,当我在其中传递变量时,resolveComponent 不起作用。如果我直接传递相同的字符串(由定义函数返回),效果很好。

我尝试了一些其他选项,但没有一个起作用。最常用的是使用全局组件,因此 GeneralButton 应该是全局的。这种方法有效,但我想创建一个完全可定制的组件,但我实际上不知道将来我想使用哪个组件,所以这对我来说不是一个好的解决方案。 (我还看到了将所有组件设置为全局的建议,我想避免这种导致性能问题的原因)。

另一种方法是覆盖 Nuxt3 自动导入并手动将所需组件导入到 DataTableBody 组件中。这也有效,并且

resolveComponent()
函数比 varibale
:is
更有效,但它与前一个有同样的问题,我不知道我将在定义()函数中获得哪个组件。如果有一种方法可以根据变量动态定义导入,那么这实际上应该有效,但我很确定这是不可能的,例如:

import {`$componentToRender`} from '#components' //This does not work and I didnt find any solution which works

实际上有办法做到这一点吗?谢谢:)

javascript vuejs3 nuxt.js nuxtjs3 nuxt3
1个回答
2
投票

您无法将变量传递给resolveComponent()方法。

<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>

但是,如果您的组件是全局的(例如:~/components/global/MyComponentName.vue 或~/components/MyComponent.global.vue),您可以像这样使用它:

<template>
  <component :is="aVariableThatHoldsComponentName" />
  This is OK ✅
</template>

请注意,只有在确定需要全局组件时才应该使用全局组件,因为即使不使用全局组件,也会在每个页面中导入。

来源

© www.soinside.com 2019 - 2024. All rights reserved.