element-plus / element-plus-nuxt-starter

🌰 A starter example for element-plus with Nuxt 3.
https://element-plus-nuxt.vercel.app
MIT License
289 stars 82 forks source link

求助:动态组件如何正确使用,是否不支持动态组件渲染 #62

Closed OSpoon closed 1 year ago

OSpoon commented 1 year ago

求助:动态组件如何正确使用,是否不支持动态组件渲染

我想通过读取路由配置渲染icon,为什么动态组件没有生效

<el-menu-item v-for="route in routes" :index="route.path" @click="toPage(route.path)">
   <el-icon color="#409EFC" class="no-inherit">
    <component :is="route?.mate?.icon" />
   </el-icon>
</el-menu-item>

相同的下面直接使用对应的icon是正常的

<el-menu-item v-for="route in routes" :index="route.path" @click="toPage(route.path)">
   <el-icon color="#409EFC" class="no-inherit">
      <el-icon-histogram />
   </el-icon>
   <span>{{route?.mate?.name}}</span>
</el-menu-item>

image

jw-foss commented 1 year ago

.. 动态组件的前提是,你直接传入组件的 Object 或者是你的这个组件要在全局注册,

请仔细阅读 Vue 文档

还有一个事情,劳烦提问的时候给足上下文,你目前给出的代码并不足以让我们能够帮助到你去 debug,这样的提问是无效的。

尽量把你相关的代码全部提上来。谢谢。

OSpoon commented 1 year ago
  1. nuxt默认已经导入的组件,也有说明icon单独使用是可以正常渲染;
  2. :is 在Vue文档中提示可以使用组件名

所以你尝试告诉我在nuxt中全局注册是想让我怎么做?

同时我也在向nuxt请求帮助,我提供了一份最小复制品,https://stackblitz.com/edit/github-ejeh3v?file=app.vue

我不认为我的使用有什么问题,至少目前来说是这样的

jw-foss commented 1 year ago

@OSpoon 确实是可以使用组件名字的,这一点我在上面也进行了回复

内部调用 resolveComponent 方法去获取组件,当你的组件没有注册的情况下,通过 string 作为参数是没有办法能够 resolve 出来任何东西的。

在你给到的复制品里也能够看到:

CleanShot 2023-03-14 at 15 26 27@2x

这个组件是没有渲染的。

如果把你的代码改成

<script setup>
import { ref, resolveComponent } from 'vue';
import CompA from './components/CompA.vue';
import CompB from './components/CompB.vue';

const currentComponent = ref(CompA);

const change = () => {
  currentComponent.value =
    currentComponent.value === CompA ? CompB : CompA;
};
</script>
<template>
  <div>
    <button @click="change">change component</button>

    <!-- Dynamic components are not rendered -->
    <component :is="currentComponent" />

    <!-- component rendered -->
    <comp-a />
    <comp-b />
  </div>
</template>

<component :is=""/> 也就能够正常的去处理了。

OSpoon commented 1 year ago

@OSpoon 确实是可以使用组件名字的,这一点我在上面也进行了回复

内部调用 resolveComponent 方法去获取组件,当你的组件没有注册的情况下,通过 string 作为参数是没有办法能够 resolve 出来任何东西的。

在你给到的复制品里也能够看到:

CleanShot 2023-03-14 at 15 26 27@2x

这个组件是没有渲染的。

如果把你的代码改成

<script setup>
import { ref, resolveComponent } from 'vue';
import CompA from './components/CompA.vue';
import CompB from './components/CompB.vue';

const currentComponent = ref(CompA);

const change = () => {
  currentComponent.value =
    currentComponent.value === CompA ? CompB : CompA;
};
</script>
<template>
  <div>
    <button @click="change">change component</button>

    <!-- Dynamic components are not rendered -->
    <component :is="currentComponent" />

    <!-- component rendered -->
    <comp-a />
    <comp-b />
  </div>
</template>

<component :is=""/> 也就能够正常的去处理了。

感谢你的帮助,我还没有在nuxt中尝试成功,但刚才尝试在仅仅包含Vuejs的项目中我的方式是正确的,https://stackblitz.com/edit/vitejs-vite-rd9mcl?file=src/App.vue

我将先去nuxt中寻找答案~

jw-foss commented 1 year ago

@OSpoon Vue 的这个能成功因为这是被正确注册的组件,Nuxt 注册的方式跟这个不太一样,<component /> 是一个特殊的组件,就像我上面说的内部用了 resolveComponent 来实现,所以在这里他并没有办法来获取到。

OSpoon commented 1 year ago

@jw-foss 非常感谢你的提醒,我已经在nuxt文档找到了正确使用动态组件的方式,目前已经可以使用了

import { resolveComponent } from 'vue';

const components = {
  'el-icon-share': resolveComponent('el-icon-share'),
  'el-icon-histogram': resolveComponent('el-icon-histogram'),
}

<el-icon color="#409EFC" class="no-inherit">
  <component :is="components[route?.mate?.icon]" />
</el-icon>