是否可以将组件作为道具传递并在 Vue 的子组件中使用它?

Is it possible to pass a component as props and use it in a child Component in Vue?

在 Vue 2.0 应用程序中,假设我们有组件 A、B 和 C。

A声明、注册并使用B

是否可以将 C 从 A 传递给 B?

像这样:

<template>
  <div class="A">
    <B :child_component="C" />
  </div>
</template>

并以某种方式在 B 中使用 C。

<template>
  <div class="B">
    <C>Something else</C>
  </div>
</template>

动机:我想创建一个在 A 中使用但从 A 其子 C 接收的通用组件 B。实际上 A 会多次使用 B 将不同的 'C' 传递给它。

如果这种方法不正确,那么在 Vue 中正确的做法是什么?

正在回答@Saurabh

我没有作为道具传递,而是尝试了B里面的建议。

<!-- this is where I Call the dynamic component in B -->

<component :is="child_component"></component>

//this is what I did in B js
components: {
 equip: Equipment
}, 
data () {
 return {
   child_component: 'equip',
   _list: []
 }
}

基本上我正在尝试渲染设备,但是动态方式

我在控制台中收到 3 个错误和一个空白页面

[Vue warn]: Error when rendering component at /home/victor/projetos/tokaai/public/src/components/EquipmentFormItem.vue:

Uncaught TypeError: Cannot read property 'name' of undefined

TypeError: Cannot read property 'setAttribute' of undefined

显然我做错了什么

您可以使用特殊属性 is 来做这种事情。可以找到动态组件的示例及其用法 here.

You can use the same mount point and dynamically switch between multiple components using the reserved element and dynamically bind to its is attribute:

您的代码如下所示:

<template>
  <div class="B">
    <component :is="child_component"> Something else</component>
  </div>
</template>

总结:

<!-- Component A -->
<template>
  <div class="A">
    <B>
      <component :is="child_component"></component>
    </B>
  </div>
</template>

<script>
import B from './B.vue';
import Equipment from './Equipment.vue';

export default {
  name: 'A',
  components: { B, Equipment },
  data() {
    return { child_component: 'equipment' };
  }
};
</script>

<!-- Component B -->
<template>
  <div class="B">
    <h1>Some content</h1>
    <slot></slot> <!-- Component C will appear here -->
  </div>
</template>

这是通过另一个组件的 props 转发自定义组件的解决方案

:is 是特殊属性,它将用于替换您的实际组件,如果您尝试将其用作组件中的道具,它将被忽略。幸运的是,您可以使用 el 之类的其他内容,然后像这样将其转发给 component

<template>
  <div>
    <component :is="el">
      <slot />
    </component>
  </div>
</template>
<script>
  export default {
    name: 'RenderDynamicChild',
    props: {
        el: {
            type: [String, Object],
            default: 'div',
        },
    },
  }
</script>

您在 el 属性中使用的任何有效元素都将用作子组件。它可以是 html 或对自定义组件的引用,或者默认情况下 div,如组件声明中指定的那样。

将自定义组件传递给 prop 有点棘手。人们会假设您在父组件的 components 属性 中声明,然后将其用于 el 属性,但这不起作用。相反,您需要在 datacomputed 属性 中包含动态组件,以便您可以在模板中将其用作道具。还要注意 AnotherComponent 不需要在 components 属性 中声明。

<template>
  <RenderDynamicChild :el="DynamicComponent">
    Hello Vue!
  </RenderDynamicChild>
</template>

<script>
import RenderDynamicChild from './DynamicChild';
import AnotherComponent from './AnotherComponent';

export default {
  name: "ParentComponent",
  components: { DynamicChild },
  data() {
    return {
      DynamicComponent: AnotherComponent,
    };
  },
};
</script>

为您的动态组件使用计算 属性 可以让您轻松地在组件之间切换:

<script>
import DynamicChild from './DynamicChild';
import AnotherComponent from './AnotherComponent';

export default {
  name: "ParentComponent",
  components: { DynamicChild },
  data() { return { count: 0 } },
  computed: {
    DynamicComponent() {
      return this.count % 2 > 1 ? AnotherComponent : 'article';
    },
  },
};
</script>

增加 this.count 以在 AnotherComponent 和简单 article html 元素之间交替。

如果您想在您的功能组件中使用另一个组件,您可以执行以下操作:

<script>
  import Vue from 'vue'
  import childComponent from './childComponent'
  Vue.component('child-component')
  export default {}
</script>


<template functional>
  <div>
    <child-component/>
  </div>
</template>

参考: https://github.com/vuejs/vue/issues/7492#issue-290242300

也许现在回答这个问题为时已晚。但我认为它可以帮助其他人解决同样的问题。

我一直在寻找一种方法来将组件传递给 vue 中的其他组件,但看起来 VUE3 有一种使用命名插槽的方法:

这是关于它的文档: https://v3.vuejs.org/guide/component-slots.html#named-slots

基本上你可以拥有:

<template>
  <div class="A">
    <slot name="ComponentC"></slot> <!-- Here will be rendered your ComponentC -->
  </div>
  <div class="A">
    <slot name="ComponentD"></slot> <!-- Here will be rendered your ComponentD -->
  </div>
  <div class="A">
    <slot></slot> <!-- This is going to be children components -->
  </div>
</template>

并且来自您的 B 组件

<template>
  <div class="B">
    <A>
      <template v-slot:ComponentC>
        <h1>Title of ComponentC </h1>
      </template>
      <template v-slot:ComponentD>
        <h1>Title of ComponentD </h1>
      </template>
      <template v-slot:default>
        <h1>Title of child component </h1>
      </template>
    </A>
  </div>
</template>