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

bfhwhh0e  于 2022-12-04  发布在  Vue.js
关注(0)|答案(5)|浏览(196)

In a Vue 2.0 app, let's say we have components A, B and C.
A declares, registers and uses B
Is it possible to pass C from A to B?
Something like this:

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

And use C in B somehow.

<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 . Actually A will use B several times passing different 'C's to it.
If this approach is not correct, what is the proper way of doing it in Vue?

Answering @Saurabh

Instead of passing as props, I tried the suggestion inside 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
[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
Apparently I'm doing something wrong

dldeef67

dldeef671#

总结:

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

nwsw7zdq2#

你可以使用特殊属性is来做这类事情。动态组件的例子和它的用法可以在这里找到。
您可以使用相同的挂载点,并使用保留元素在多个组件之间动态切换,以及动态绑定到其is属性。
下面是is如何与导入的组件或作为prop传递的组件一起使用:

<template>
  <div class="B">
    <component :is="myImportedComponent">Something</component>
    --- or ---
    <component :is="myPassedComponent">Something else</component>
  </div>
</template>

<script>
import myImportedComponent from "@/components/SomeComponent.vue"

export default {
    props: {
        myPassedComponent: Object
    },

    components: {
        myImportedComponent
    },
}
</script>
8oomwypt

8oomwypt3#

下面是通过另一个组件的属性转发自定义组件的解决方案
: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属性中,以便在模板中将其用作prop。还要注意,AnotherComponent不't需要在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元素之间交替。

azpvetkf

azpvetkf4#

也许现在回答这个问题已经太晚了,但我认为它可以帮助其他人解决同样的问题。
我一直在寻找一种方法来传递组件抛出其他在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>
gz5pxeao

gz5pxeao5#

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

<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

相关问题