vue wrap another component, passing props and events

后端 未结 1 1720
野趣味
野趣味 2020-12-15 07:14

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:



        
相关标签:
1条回答
  • 2020-12-15 07:25

    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>

    0 讨论(0)
提交回复
热议问题