--- 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 | undefined>; type GenerateSlotsFromSlotMap = { [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> { /** * 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; ```