--- category: Component outline: deep --- # createReusableTemplate Define and reuse template inside the component scope. ## Motivation It's common to have the need to reuse some part of the template. For example: ```vue ``` We'd like to reuse our code as much as possible. So normally we might need to extract those duplicated parts into a component. However, in a separated component you lose the ability to access the local bindings. Defining props and emits for them can be tedious sometimes. So this function is made to provide a way for defining and reusing templates inside the component scope. ## Usage In the previous example, we could refactor it to: ```vue ``` - `` will register the template and renders nothing. - `` will render the template provided by ``. - `` must be used before ``. > **Note**: It's recommended to extract as separate components whenever possible. Abusing this function might lead to bad practices for your codebase. ### Options API When using with [Options API](https://vuejs.org/guide/introduction.html#api-styles), you will need to define `createReusableTemplate` outside of the component setup and pass to the `components` option in order to use them in the template. ```vue ``` ### Passing Data You can also pass data to the template using slots: - Use `v-slot="..."` to access the data on `` - Directly bind the data on `` to pass them to the template ```vue ``` ### TypeScript Support `createReusableTemplate` accepts a generic type to provide type support for the data passed to the template: ```vue ``` Optionally, if you are not a fan of array destructuring, the following usages are also legal: ```vue ``` ```vue ``` ::: warning Passing boolean props without `v-bind` is not supported. See the [Caveats](#boolean-props) section for more details. ::: ### Props and Attributes By default, all props and attributes passed to `` will be passed to the template. If you don't want certain props to be passed to the DOM, you need to define the runtime props: ```ts import { createReusableTemplate } from '@vueuse/core' const [DefineTemplate, ReuseTemplate] = createReusableTemplate({ props: { msg: String, enable: Boolean, } }) ``` If you don't want to pass any props to the template, you can pass the `inheritAttrs` option: ```ts import { createReusableTemplate } from '@vueuse/core' const [DefineTemplate, ReuseTemplate] = createReusableTemplate({ inheritAttrs: false, }) ``` ### Passing Slots It's also possible to pass slots back from ``. You can access the slots on `` from `$slots`: ```vue ``` ## Caveats ### Boolean props As opposed to Vue's behavior, props defined as `boolean` that were passed without `v-bind` or absent will be resolved into an empty string or `undefined` respectively: ```vue ``` ## References This function is migrated from [vue-reuse-template](https://github.com/antfu/vue-reuse-template). Existing Vue discussions/issues about reusing template: - [Discussion on Reusing Templates](https://github.com/vuejs/core/discussions/6898) Alternative Approaches: - [Vue Macros - `namedTemplate`](https://vue-macros.sxzz.moe/features/named-template.html) - [`unplugin-vue-reuse-template`](https://github.com/liulinboyi/unplugin-vue-reuse-template) ## Type Declarations ```ts type ObjectLiteralWithPotentialObjectLiterals = Record< string, Record | undefined > type GenerateSlotsFromSlotMap< T extends ObjectLiteralWithPotentialObjectLiterals, > = { [K in keyof T]: Slot } export type DefineTemplateComponent< Bindings extends Record, MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals, > = DefineComponent & { new (): { $slots: { default: ( _: Bindings & { $slots: GenerateSlotsFromSlotMap }, ) => any } } } export type ReuseTemplateComponent< Bindings extends Record, MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals, > = DefineComponent & { new (): { $slots: GenerateSlotsFromSlotMap } } export type ReusableTemplatePair< Bindings extends Record, MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals, > = [ DefineTemplateComponent, ReuseTemplateComponent, ] & { define: DefineTemplateComponent reuse: ReuseTemplateComponent } export interface CreateReusableTemplateOptions< Props extends Record, > { /** * Inherit attrs from reuse component. * * @default true */ inheritAttrs?: boolean /** * Props definition for reuse component. */ props?: ComponentObjectPropsOptions } /** * This function creates `define` and `reuse` components in pair, * It also allow to pass a generic to bind with type. * * @see https://vueuse.org/createReusableTemplate * * @__NO_SIDE_EFFECTS__ */ export declare function createReusableTemplate< Bindings extends Record, MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals = Record<"default", undefined>, >( options?: CreateReusableTemplateOptions, ): ReusableTemplatePair ```