vue项目setup开发过程中的一些问题--动态组件不生效问题

299 阅读2分钟

:is="item.type + 'Component'" 和 :is="components[item.type + 'Component']" 的不同之处在于 Vue 的动态组件解析逻辑。下面是原因的详细解释:

  1. Vue 的动态组件解析逻辑

:is 属性支持两种类型的值:

字符串:表示一个全局注册的组件名称。

组件对象:一个 Vue 组件实例(本地或动态注册的组件)。

  • 为什么 :is="item.type + 'Component'" 可能无效: 当 item.type + 'Component' 是字符串时,Vue 会尝试在全局注册的组件列表中查找对应的组件。 如果未注册为全局组件,Vue 无法找到对应的组件,因此不会渲染。

  • 为什么 :is="components[item.type + 'Component']" 生效: components[item.type + 'Component'] 返回的是组件对象(不是字符串)。 Vue 直接使用这个对象,无需在全局查找对应的组件名称,因此可以正确渲染。

  1. 全局注册和局部注册的区别 如果组件是全局注册的: item.type + 'Component' 可以作为字符串直接工作,因为 Vue 能从全局组件中找到它。

如果组件是局部注册的: item.type + 'Component' 作为字符串无效,因为局部组件不会自动注册为全局组件。你必须手动将局部组件对象传递给 :is。

在你的代码中,inputComponent 是局部注册的,因此需要通过对象形式(components[item.type + 'Component'])绑定。

  1. 拼接后的字符串无法解析为组件 item.type + 'Component' 是动态拼接的字符串,Vue 无法在运行时直接将其解析为组件名称。

示例:

<template>
  <component :is="'inputComponent'" /> <!-- 这个可以生效,如果 'inputComponent' 是全局注册的 -->
  <component :is="inputComponent" /> <!-- 这个可以生效,因为它是一个组件对象 -->
</template>

<script>
import inputComponent from './inputComponent.vue'; 

export default {
  components: {

    inputComponent, // 局部注册

  }, 
}; 
</script>

在局部注册中,直接通过字符串引用('inputComponent')的方式不会生效,必须传递组件对象。

  1. 最佳实践:使用组件对象 为了兼容局部注册和动态解析,建议使用组件对象形式:
const components = {
    inputComponent,
};

然后在模板中:

<component :is="components[item.type + 'Component']" />

这种方式更安全且不会依赖全局注册。

总结 :is="item.type + 'Component'" 不生效的原因是它生成了一个字符串,而字符串只能匹配全局注册的组件。

:is="components[item.type + 'Component']" 生效的原因是它返回了一个组件对象,而组件对象可以直接被 Vue 渲染。

如果需要全局解析,可以将组件全局注册:

app.component('inputComponent', inputComponent);

否则,推荐通过对象映射的方式使用局部组件。