0
# Template Composition
1
2
Advanced template composition utilities for creating reusable templates, template-based promises, and template reference helpers. These utilities enable sophisticated template patterns and component composition strategies.
3
4
## Capabilities
5
6
### Template Reusability
7
8
#### createReusableTemplate
9
10
Create reusable template components that can be defined once and reused multiple times.
11
12
```typescript { .api }
13
/**
14
* Create a pair of components for defining and reusing templates
15
* @param options - Template configuration options
16
* @returns Template component pair with define and reuse components
17
*/
18
function createReusableTemplate<
19
Bindings extends Record<string, any> = {},
20
Props extends Record<string, any> = {},
21
MapSlotNameToSlotProps extends Record<string, any> = {}
22
>(
23
options?: CreateReusableTemplateOptions<Props>
24
): ReusableTemplatePair<Bindings, MapSlotNameToSlotProps>;
25
26
interface CreateReusableTemplateOptions<Props extends Record<string, any>> {
27
inheritAttrs?: boolean;
28
props?: ComponentObjectPropsOptions<Props>;
29
}
30
31
type ReusableTemplatePair<
32
Bindings extends Record<string, any>,
33
MapSlotNameToSlotProps extends Record<string, any>
34
> = [
35
DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>,
36
ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>
37
] & {
38
define: DefineTemplateComponent<Bindings, MapSlotNameToSlotProps>;
39
reuse: ReuseTemplateComponent<Bindings, MapSlotNameToSlotProps>;
40
};
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import { createReusableTemplate } from "@vueuse/core";
47
48
// Create template pair
49
const [DefineTemplate, ReuseTemplate] = createReusableTemplate<{ name: string }>();
50
51
// In your component template:
52
// <DefineTemplate v-slot="{ name }">
53
// <h1>Hello {{ name }}!</h1>
54
// </DefineTemplate>
55
//
56
// <ReuseTemplate name="World" />
57
// <ReuseTemplate name="Vue" />
58
```
59
60
#### createTemplatePromise
61
62
Create Promise-based templates for modal dialogs, confirmations, and async interactions.
63
64
```typescript { .api }
65
/**
66
* Create Promise-based template components for modal interactions
67
* @param options - Template promise configuration options
68
* @returns Template promise component and utilities
69
*/
70
function createTemplatePromise<Return = any, Args extends any[] = []>(
71
options?: TemplatePromiseOptions
72
): TemplatePromiseReturn<Return, Args>;
73
74
interface TemplatePromiseReturn<Return, Args extends any[]> {
75
TemplatePromise: DefineComponent<TemplatePromiseProps<Return, Args>>;
76
start: (...args: Args) => Promise<Return>;
77
close: () => void;
78
}
79
80
interface TemplatePromiseProps<Return, Args extends any[]> {
81
promise: Promise<Return> | undefined;
82
resolve: (v: Return | Promise<Return>) => void;
83
reject: (v: any) => void;
84
args: Args;
85
isResolving: boolean;
86
options: TemplatePromiseOptions;
87
}
88
89
interface TemplatePromiseOptions {
90
singleton?: boolean;
91
transition?: TransitionGroupProps;
92
}
93
```
94
95
**Usage Examples:**
96
97
```typescript
98
import { createTemplatePromise } from "@vueuse/core";
99
100
// Create confirmation dialog
101
const { TemplatePromise, start } = createTemplatePromise<boolean>();
102
103
// Use in template:
104
// <TemplatePromise v-slot="{ resolve, reject, args }">
105
// <div class="modal">
106
// <p>Are you sure?</p>
107
// <button @click="resolve(true)">Yes</button>
108
// <button @click="resolve(false)">No</button>
109
// </div>
110
// </TemplatePromise>
111
112
// Trigger programmatically
113
const confirmed = await start();
114
```
115
116
### Template References
117
118
#### templateRef
119
120
Template reference helper with type safety and automatic cleanup.
121
122
```typescript { .api }
123
/**
124
* Type-safe template reference helper
125
* @param key - Template ref key or element selector
126
* @param initialValue - Initial ref value
127
* @returns Template ref with enhanced capabilities
128
*/
129
function templateRef<T extends Element | ComponentPublicInstance = Element>(
130
key?: string | number | symbol,
131
initialValue?: T | null
132
): Readonly<Ref<T | null>>;
133
```
134
135
**Usage Examples:**
136
137
```typescript
138
import { templateRef } from "@vueuse/core";
139
140
// In setup
141
const buttonRef = templateRef<HTMLButtonElement>('button');
142
143
// In template: <button ref="button">Click me</button>
144
145
// Access element
146
console.log(buttonRef.value?.textContent);
147
```
148
149
#### useTemplateRefsList
150
151
Manage multiple template references with reactive list support.
152
153
```typescript { .api }
154
/**
155
* Reactive template references list for v-for scenarios
156
* @returns Template refs list with reactive updates
157
*/
158
function useTemplateRefsList<T = Element>(): [
159
Ref<T[]>,
160
(el: T | ComponentPublicInstance | Element | null) => void
161
];
162
```
163
164
**Usage Examples:**
165
166
```typescript
167
import { useTemplateRefsList } from "@vueuse/core";
168
169
// In setup
170
const [itemRefs, setItemRef] = useTemplateRefsList<HTMLDivElement>();
171
172
// In template:
173
// <div v-for="item in items" :key="item.id" :ref="setItemRef">
174
// {{ item.name }}
175
// </div>
176
177
// Access elements
178
itemRefs.value.forEach(el => console.log(el.textContent));
179
```
180
181
### Function Utilities
182
183
#### createUnrefFn
184
185
Create functions that automatically unref their arguments.
186
187
```typescript { .api }
188
/**
189
* Create a function that automatically unrefs its arguments
190
* @param fn - Function to enhance with auto-unref
191
* @returns Function that accepts refs and automatically unrefs them
192
*/
193
function createUnrefFn<T extends AnyFn>(fn: T): UnrefFnReturn<T>;
194
195
type UnrefFnReturn<T extends AnyFn> = (
196
...args: ToRefs<Parameters<T>>
197
) => ReturnType<T>;
198
```
199
200
**Usage Examples:**
201
202
```typescript
203
import { createUnrefFn, ref } from "@vueuse/core";
204
205
// Create unref function
206
const add = createUnrefFn((a: number, b: number) => a + b);
207
208
// Use with refs
209
const x = ref(1);
210
const y = ref(2);
211
const result = add(x, y); // Automatically unrefs x and y
212
```
213
214
#### unrefElement
215
216
Unref element from template refs, component instances, or plain elements.
217
218
```typescript { .api }
219
/**
220
* Unref element from various ref types
221
* @param elRef - Element reference (ref, component, or element)
222
* @returns Unrefed HTML element or null
223
*/
224
function unrefElement<T extends MaybeElement>(
225
elRef: MaybeElementRef<T>
226
): UnwrapNestedRefs<T>;
227
228
type MaybeElement = HTMLElement | SVGElement | VueInstance | undefined | null;
229
type MaybeElementRef<T extends MaybeElement = MaybeElement> = MaybeRef<T>;
230
```
231
232
**Usage Examples:**
233
234
```typescript
235
import { unrefElement, ref } from "@vueuse/core";
236
237
const elementRef = ref<HTMLDivElement>();
238
const componentRef = ref<ComponentPublicInstance>();
239
240
// Unref to get actual DOM element
241
const element = unrefElement(elementRef);
242
const componentElement = unrefElement(componentRef); // Gets component.$el
243
```
244
245
### Reactive Composition
246
247
#### computedInject
248
249
Computed with dependency injection support.
250
251
```typescript { .api }
252
/**
253
* Computed with dependency injection from parent components
254
* @param key - Injection key
255
* @param fn - Computation function receiving injected value
256
* @param defaultValue - Default value if injection fails
257
* @returns Computed ref with injected dependency
258
*/
259
function computedInject<T, K>(
260
key: InjectionKey<T> | string,
261
fn: (source: T, oldValue: K | undefined) => K,
262
defaultValue?: T
263
): ComputedRef<K>;
264
```
265
266
**Usage Examples:**
267
268
```typescript
269
import { computedInject, provide, ref } from "@vueuse/core";
270
271
// Parent provides theme
272
const theme = ref('dark');
273
provide('theme', theme);
274
275
// Child computes based on injected theme
276
const computedStyles = computedInject('theme', (theme) => ({
277
background: theme === 'dark' ? '#000' : '#fff',
278
color: theme === 'dark' ? '#fff' : '#000'
279
}));
280
```
281
282
### Event Management
283
284
#### createEventHook
285
286
Create custom event hooks for component communication.
287
288
```typescript { .api }
289
/**
290
* Create custom event hook for component events
291
* @returns Event hook with trigger and on methods
292
*/
293
function createEventHook<T = any>(): EventHook<T>;
294
295
interface EventHook<T = any> {
296
on: (fn: (param: T) => void) => void;
297
off: (fn: (param: T) => void) => void;
298
trigger: (param: T) => Promise<unknown[]>;
299
}
300
```
301
302
**Usage Examples:**
303
304
```typescript
305
import { createEventHook } from "@vueuse/core";
306
307
// Create custom event
308
const onDataLoaded = createEventHook<{ data: any[] }>();
309
310
// Listen to event
311
onDataLoaded.on(({ data }) => {
312
console.log('Data loaded:', data);
313
});
314
315
// Trigger event
316
onDataLoaded.trigger({ data: [1, 2, 3] });
317
```
318
319
## Shared Types
320
321
```typescript { .api }
322
// Component types
323
type VueInstance = ComponentPublicInstance;
324
type MaybeElement = HTMLElement | SVGElement | VueInstance | undefined | null;
325
type MaybeElementRef<T extends MaybeElement = MaybeElement> = MaybeRef<T>;
326
327
// Template component types
328
type DefineTemplateComponent<
329
Bindings extends Record<string, any>,
330
MapSlotNameToSlotProps extends Record<string, any>
331
> = DefineComponent & {
332
new(): {
333
$slots: {
334
default: (_: Bindings & {
335
$slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps>
336
}) => any
337
}
338
}
339
};
340
341
type ReuseTemplateComponent<
342
Bindings extends Record<string, any>,
343
MapSlotNameToSlotProps extends Record<string, any>
344
> = DefineComponent<Bindings> & {
345
new(): {
346
$slots: GenerateSlotsFromSlotMap<MapSlotNameToSlotProps>
347
}
348
};
349
350
// Function utility types
351
type AnyFn = (...args: any[]) => any;
352
type ToRefs<T extends readonly unknown[]> = {
353
[K in keyof T]: MaybeRef<T[K]>
354
};
355
356
type UnrefFnReturn<T extends AnyFn> = (
357
...args: ToRefs<Parameters<T>>
358
) => ReturnType<T>;
359
360
// Event hook types
361
interface EventHookOn<T = any> {
362
(fn: (param: T) => void): void;
363
}
364
365
interface EventHookOff<T = any> {
366
(fn: (param: T) => void): void;
367
}
368
369
interface EventHookTrigger<T = any> {
370
(param: T): Promise<unknown[]>;
371
}
372
```