简体   繁体   中英

vue wrap another component, passing props and events

How can I write my component to wrap another vue component, while my wrapper component get some extra props? My wrapper template component should be:

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

and the wrapper props:

props: {
  prop1: String,
  prop2: String
}

Here I want to wrap a table component, and pass to the table component all the props and events that were passed to the wrapper, beside two extra props prop1 and prop2 . What is the correct way of doing this in vue? And is there a solution for events too?

Place the component you wish to wrap into the template of the wrapper component, add v-bind="$attrs" v-on="$listeners" to that component tag, then add the inner component (and, optionally, inheritAttrs: false ) to the wrapper component's config object.

Vue's documentation doesn't seem to cover this in a guide or anything, but docs for $attrs , $listeners , and inheritAttrs can be found in Vue's API documentation . Also, a term that may help you when searching for this topic in the future is " Higher-Order Component " (HOC) - which is basically the same as your use of "wrapper component". (This term is how I originally found $attrs)

For example...

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

Edit : Alternatively, you may want to use dynamic components via the is attribute so you can pass in the component to be wrapped as a prop (closer to the higher-order component idea) instead of it always being the same inner component. For example:

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

Edit 2 : The part of OP's original question that I missed was passing all props EXCEPT one or two. This is handled by explicitly defining the prop on the wrapper. To quote the documentation for $attrs :

Contains parent-scope attribute bindings (except for class and style) that are not recognized (and extracted) as props

For example, example1 is recognized and extracted as a prop in the snippet below, so it doesn't get included as part of the $attrs being passed down.

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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