简体   繁体   English

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

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

In a Vue 2.0 app, let's say we have components A, B and C.在 Vue 2.0 应用程序中,假设我们有组件 A、B 和 C。

A declares, registers and uses B A 声明、注册和使用 B

Is it possible to pass C from A to B?是否可以将 C 从 A 传递到 B?

Something like this:像这样的东西:

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

And use C in B somehow.并以某种方式在 B 中使用 C。

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

The motivation: I want to create a generic component B that is used in A but receives from A its child C .动机:我想创建一个在A中使用但从A接收其子C的通用组件B Actually A will use B several times passing different 'C's to it.实际上A会多次使用B传递不同的 'C' 给它。

If this approach is not correct, what is the proper way of doing it in Vue?如果这种方法不正确,那么在 Vue 中正确的做法是什么?

Answering @Saurabh回答@Saurabh

Instead of passing as props, I tried the suggestion inside B.我没有作为道具传递,而是尝试了 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: []
 }
}

Basically I'm trying to render Equipment, but the dynamic way基本上我正在尝试渲染设备,但是动态方式

I get 3 errors in console and a blank page我在控制台中收到 3 个错误和一个空白页

[Vue warn]: Error when rendering component at /home/victor/projetos/tokaai/public/src/components/EquipmentFormItem.vue: [Vue 警告]:在 /home/victor/projetos/tokaai/public/src/components/EquipmentFormItem.vue 处渲染组件时出错:

Uncaught TypeError: Cannot read property 'name' of undefined未捕获的类型错误:无法读取未定义的属性“名称”

TypeError: Cannot read property 'setAttribute' of undefined TypeError:无法读取未定义的属性“setAttribute”

Apparently I'm doing something wrong显然我做错了什么

Summing up:加起来:

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

You can use special attribute is for doing this kind of thing.你可以使用特殊is来做这种事情。 Example of dynamic component and its usage can be found 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:您可以使用相同的挂载点并使用保留元素在多个组件之间动态切换并动态绑定到其 is 属性:

Your code will look like following:您的代码将如下所示:

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

Here's solution to forward custom component through props of another component这是通过另一个组件的道具转发自定义组件的解决方案

:is is special attribute and it will be used to replace your actual component and it will be ignored if you try to use it as a prop in your component. :is是特殊属性,它将用于替换您的实际组件,如果您尝试将其用作组件中的道具,它将被忽略。 Luckily you can use something else like el and then forward this to component like so:幸运的是,您可以使用el之类的其他东西,然后将其转发给component ,如下所示:

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

Any valid element you use in el attribute will be used as a child component.您在el属性中使用的任何有效元素都将用作子组件。 It can be html or reference to your custom component or div by default as specified in component declaration.默认情况下,它可以是 html 或对您的自定义组件或div的引用,如组件声明中指定的那样。

Passing custom component to prop is little bit tricky.将自定义组件传递给 prop 有点棘手。 One would assume you declare in a components property of parent component and then use it for el attribute but this doesn't work.有人会假设您在父组件的components属性中声明,然后将其用于el属性,但这不起作用。 Instead you need to have your dynamic component in data or computed property so you can use it in a template as a prop.相反,您需要将动态组件放在datacomputed属性中,以便可以在模板中将其用作道具。 Also note AnotherComponent doesn't need to be declared in components property.另请注意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>

Using computed property for your dynamic component allows you to switch between components easily:为您的动态组件使用计算属性允许您轻松地在组件之间切换:

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

Increase this.count to alternate between AnotherComponent and simple article html element.增加this.count以在AnotherComponent和简单的article html 元素之间交替。

If you would like to use another component within your functional component you can do the following:如果您想在功能组件中使用另一个组件,您可以执行以下操作:

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


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

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

Maybe it's too late to answer this question.也许现在回答这个问题为时已晚。 But I think it could help others with this same issue.但我认为它可以帮助其他人解决同样的问题。

I've been looking for a way to pass components throw others in vue, but it looks that VUE3 have a approach for that using named slots:我一直在寻找一种在 vue 中传递组件的方法,但看起来 VUE3 有一种使用命名插槽的方法:

Here it's the documentation about that: https://v3.vuejs.org/guide/component-slots.html#named-slots这是关于它的文档: https ://v3.vuejs.org/guide/component-slots.html#named-slots

Basically you can have:基本上你可以拥有:

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

And from your B component从你的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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM