vue 包装另一个组件,传递道具和事件

Posted

技术标签:

【中文标题】vue 包装另一个组件,传递道具和事件【英文标题】:vue wrap another component, passing props and events 【发布时间】:2018-11-20 21:27:07 【问题描述】:

如何编写我的组件来包装另一个 vue 组件,同时我的包装器组件获得一些额外的道具?我的包装模板组件应该是:

<wrapper-component>
   <v-table></v-table> <!-- pass to v-table all the props beside prop1 and prop2 -->
</wrapper-component>

和包装道具:

props: 
  prop1: String,
  prop2: String

这里我想包装一个表格组件,并将传递给包装器的所有道具和事件传递给表格组件,除了两个额外的道具prop1prop2。在 vue 中这样做的正确方法是什么? 事件也有解决方案吗?

【问题讨论】:

这就是 $listeners 和 $props 的具体用途。 【参考方案1】:

将您希望包装的组件放入包装器组件的模板中,将v-bind="$attrs" v-on="$listeners" 添加到该组件标签,然后将内部组件(以及可选的inheritAttrs: false)添加到包装器组件的配置对象中。

Vue 的文档似乎没有在指南或其他任何内容中介绍这一点,但 $attrs、$listeners 和 inheritAttrs 的文档可以在 Vue's API documentation 中找到。此外,在将来搜索此主题时可能会对您有所帮助的术语是“Higher-Order Component”(HOC) - 这与您对“包装器组件”的使用基本相同。 (这个词是我最初找到 $attrs 的方式)

例如...

<!-- WrapperComponent.vue -->
<template>
    <div class="wrapper-component">
        <v-table v-bind="$attrs" v-on="$listeners"></v-table>
    </div>
</template>

<script>
    import Table from './BaseTable'

    export default 
        components:  'v-table': Table ,
        inheritAttrs: false // optional
    
</script>

编辑:或者,您可能希望通过is attribute 使用dynamic components,这样您就可以传入要包装为道具的组件(更接近高阶组件的想法)而不是它总是相同的内部组件。例如:

<!-- WrapperComponent.vue -->
<template>
    <div class="wrapper-component">
        <component :is="wraps" v-bind="$attrs" v-on="$listeners"></component>
    </div>
</template>

<script>
    export default 
        inheritAttrs: false, // optional
        props: ['wraps']
    
</script>

编辑 2:我错过的 OP 原始问题的一部分是传递所有道具,除了一两个。这是通过显式定义包装器上的道具来处理的。引用$attrs的文档:

包含不被识别(和提取)为道具的父范围属性绑定(类和样式除外)

例如,example1 在下面的 sn-p 中被识别并提取为一个 prop,因此它不会作为 $attrs 的一部分被包含在内。

Vue.component('wrapper-component',  
  template: `
    <div class="wrapper-component">
        <component :is="wraps" v-bind="$attrs" v-on="$listeners"></component>
    </div>
  `,
  // NOTE: "example1" is explicitly defined on wrapper, not passed down to nested component via $attrs
  props: ['wraps', 'example1']
)

Vue.component('posts', 
  template: `
    <div>
      <div>Posts component</div>
      <div v-text="example1"></div>
      <div v-text="example2"></div>
      <div v-text="example3"></div>
    </div>
  `,
  props: ['example1', 'example2', 'example3'],
)

new Vue(
  el: '#app',
  template: `
    <wrapper-component wraps="posts"
      example1="example1"
      example2="example2"
      example3="example3"
    ></wrapper-component>
  `,
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

【讨论】:

感谢您的回答,但是 OP 询问如何排除某些道具。例如,假设我包装了一个接受 v-model 和 timeZoneProp 的日期选择器。我的选择器包装器有两个道具 value(v-model) 和 timeZoneProp 。现在我希望将 timeZoneProp 传递给日期选择器,但我不希望按原样传递 v-model,因为在包装器内部我对 v-model 进行了一些数据转换,然后注入到选择器.如何解决这种情况,即排除某些“道具”,但使用 $atts 传递其余部分。在此先感谢 @SainathS.R 再次回顾这个答案,你是绝对正确的。我会更新的,谢谢!

以上是关于vue 包装另一个组件,传递道具和事件的主要内容,如果未能解决你的问题,请参考以下文章

Vue渲染功能:在没有包装器的情况下将插槽包含到子组件中

Vue路由器将道具传递给动态加载的孩子

Vue - 通过路由器将道具传递给组件

如何在 Vue.js 中将实例化的 Vue 组件作为道具传递?

vue,发射与传递函数作为道具

无法将道具复制到Vue中子组件中的数据