0
# Component Definition
1
2
Core macros for Vue component definition and configuration.
3
4
## Capabilities
5
6
### Define Options
7
8
Define component options within `<script setup>` blocks.
9
10
```typescript { .api }
11
/**
12
* Define component options (Vue 2.7+ / Vue 3.0-3.2)
13
* @param options - Component options object
14
*/
15
declare function defineOptions<
16
RawBindings = {},
17
D = {},
18
C extends ComputedOptions = {},
19
M extends MethodOptions = {},
20
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
21
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
22
>(
23
options?: ComponentOptionsWithoutProps<
24
{},
25
RawBindings,
26
D,
27
C,
28
M,
29
Mixin,
30
Extends
31
> & {
32
emits?: undefined;
33
expose?: undefined;
34
slots?: undefined;
35
}
36
): void;
37
38
// Component options type (from Vue)
39
type ComponentOptionsWithoutProps<
40
V = {},
41
D = {},
42
C extends ComputedOptions = {},
43
M extends MethodOptions = {},
44
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
45
Extends extends ComponentOptionsMixin = ComponentOptionsMixin
46
> = ComponentOptionsBase<V, D, C, M, Mixin, Extends> & {
47
props?: undefined;
48
} & ThisType<CreateComponentPublicInstance<{}, RawBindings, D, C, M, Mixin, Extends>>;
49
```
50
51
**Usage Examples:**
52
53
```vue
54
<script setup>
55
import { someDirective } from './directives';
56
import { mixinA, mixinB } from './mixins';
57
58
// Define component options
59
defineOptions({
60
name: "MyComponent",
61
inheritAttrs: false,
62
63
// Local registrations
64
components: {
65
CustomButton: () => import('./CustomButton.vue'),
66
},
67
68
directives: {
69
focus: someDirective,
70
},
71
72
// Mixins and extension
73
mixins: [mixinA, mixinB],
74
extends: BaseComponent,
75
76
// Lifecycle hooks
77
beforeCreate() {
78
console.log('Component being created');
79
},
80
81
created() {
82
console.log('Component created');
83
},
84
85
// Additional options
86
provide() {
87
return {
88
theme: 'dark',
89
};
90
},
91
});
92
93
// Your composition API code
94
const count = ref(0);
95
</script>
96
```
97
98
### Define Slots
99
100
Define component slots with TypeScript support.
101
102
```typescript { .api }
103
/**
104
* Define component slots with types (Vue 2.7+ / Vue 3.0-3.2)
105
* @returns Slots object with type definitions
106
*/
107
declare function defineSlots<
108
S extends Record<string, any> = Record<string, any>
109
>(): UnwrapSlotsType<S>;
110
111
// Slots utility types
112
type UnwrapSlotsType<S> = {
113
[K in keyof S]: S[K] extends (...args: any[]) => any ? S[K] : Slot<S[K]>;
114
};
115
116
type Slot<T = any> = (...args: T extends any ? [T] : []) => VNode[];
117
118
// Slots type inference
119
type SlotsType<T extends Record<string, any>> = {
120
[K in keyof T]: T[K] extends (...args: infer P) => any
121
? (...args: P) => VNode[]
122
: Slot<T[K]>;
123
};
124
```
125
126
**Usage Examples:**
127
128
```vue
129
<script setup>
130
// Define slots with types
131
const slots = defineSlots<{
132
default(): any;
133
header(props: { title: string; level: number }): any;
134
footer(props: { year: number }): any;
135
item(props: { item: any; index: number }): any;
136
}>();
137
138
// Check if slots exist
139
const hasHeader = !!slots.header;
140
const hasFooter = !!slots.footer;
141
142
// Use in render logic
143
function renderContent() {
144
return [
145
slots.header?.({ title: "My Title", level: 1 }),
146
slots.default?.(),
147
slots.footer?.({ year: new Date().getFullYear() }),
148
];
149
}
150
</script>
151
152
<template>
153
<div class="component">
154
<header v-if="hasHeader">
155
<slot name="header" :title="title" :level="1" />
156
</header>
157
158
<main>
159
<slot />
160
</main>
161
162
<footer v-if="hasFooter">
163
<slot name="footer" :year="2024" />
164
</footer>
165
</div>
166
</template>
167
```
168
169
### Define Emit
170
171
Define single emit function with enhanced typing.
172
173
```typescript { .api }
174
/**
175
* Define single emit function with enhanced typing
176
* @param name - Event name
177
* @returns Emit function for the specified event
178
*/
179
declare function defineEmit<T extends (...args: any[]) => any>(
180
name: string
181
): T;
182
183
/**
184
* Define emit with payload type
185
* @param name - Event name
186
* @returns Emit function with typed payload
187
*/
188
declare function defineEmit<T = any>(
189
name: string
190
): (payload: T) => void;
191
192
// Emit function types
193
type EmitFunction<T> = T extends (...args: infer P) => any
194
? (...args: P) => void
195
: (payload: T) => void;
196
```
197
198
**Usage Examples:**
199
200
```vue
201
<script setup>
202
// Define individual emit functions
203
const emitUpdate = defineEmit<(value: string) => void>("update");
204
const emitChange = defineEmit<(oldValue: string, newValue: string) => void>("change");
205
const emitDelete = defineEmit("delete"); // No payload
206
const emitSelect = defineEmit<{ id: number; name: string }>("select");
207
208
// Usage in component logic
209
function handleInput(event: Event) {
210
const value = (event.target as HTMLInputElement).value;
211
emitUpdate(value);
212
}
213
214
function handleChange(oldVal: string, newVal: string) {
215
emitChange(oldVal, newVal);
216
}
217
218
function handleDelete() {
219
emitDelete();
220
}
221
222
function handleSelect(item: { id: number; name: string }) {
223
emitSelect(item);
224
}
225
</script>
226
227
<template>
228
<div>
229
<input @input="handleInput" @change="handleChange" />
230
<button @click="handleDelete">Delete</button>
231
<button @click="handleSelect({ id: 1, name: 'Item' })">Select</button>
232
</div>
233
</template>
234
```
235
236
### Define Render
237
238
Define render function for component.
239
240
```typescript { .api }
241
/**
242
* Define render function for component
243
* @param render - Render function
244
*/
245
declare function defineRender(render: RenderFunction): void;
246
247
/**
248
* Define render function with JSX
249
* @param render - JSX render function
250
*/
251
declare function defineRender(render: () => JSX.Element): void;
252
253
// Render function types
254
type RenderFunction = (
255
props: Record<string, any>,
256
context: SetupContext
257
) => VNode | VNode[] | string | number | null | undefined;
258
259
interface SetupContext<E = EmitsOptions> {
260
attrs: Data;
261
slots: Slots;
262
emit: EmitFunction<E>;
263
expose: (exposed?: Record<string, any>) => void;
264
}
265
```
266
267
**Usage Examples:**
268
269
```vue
270
<script setup>
271
import { h } from 'vue';
272
273
// Props for render function
274
interface Props {
275
title: string;
276
items: Array<{ id: number; name: string }>;
277
}
278
279
const props = defineProps<Props>();
280
281
// Define render function with h()
282
defineRender(() => {
283
return h('div', { class: 'container' }, [
284
h('h1', props.title),
285
h('ul',
286
props.items.map(item =>
287
h('li', { key: item.id }, item.name)
288
)
289
),
290
]);
291
});
292
293
// Alternative: JSX render function
294
// defineRender(() => (
295
// <div class="container">
296
// <h1>{props.title}</h1>
297
// <ul>
298
// {props.items.map(item => (
299
// <li key={item.id}>{item.name}</li>
300
// ))}
301
// </ul>
302
// </div>
303
// ));
304
</script>
305
```
306
307
### Export Expose
308
309
Export values for parent component access.
310
311
```typescript { .api }
312
/**
313
* Export values for parent component access via template refs
314
* @param exposed - Object with exposed values
315
*/
316
declare function exportExpose<T extends Record<string, any>>(
317
exposed: T
318
): void;
319
320
// Alternative syntax using variable names
321
declare function exportExpose<T extends Record<string, any>>(): T;
322
```
323
324
**Usage Examples:**
325
326
```vue
327
<script setup>
328
import { ref, computed } from 'vue';
329
330
const count = ref(0);
331
const message = ref('Hello');
332
333
const doubleCount = computed(() => count.value * 2);
334
335
function increment() {
336
count.value++;
337
}
338
339
function reset() {
340
count.value = 0;
341
message.value = 'Hello';
342
}
343
344
// Export specific methods and values
345
exportExpose({
346
count: readonly(count),
347
message: readonly(message),
348
doubleCount,
349
increment,
350
reset,
351
352
// Can also expose computed or reactive values
353
state: computed(() => ({
354
count: count.value,
355
message: message.value,
356
})),
357
});
358
</script>
359
```
360
361
## Type Definitions
362
363
Supporting types for component definition macros.
364
365
```typescript { .api }
366
// Component option types from Vue
367
interface ComputedOptions {
368
[key: string]: ComputedGetter<any> | WritableComputedOptions<any>;
369
}
370
371
interface MethodOptions {
372
[key: string]: Function;
373
}
374
375
interface ComponentOptionsMixin {
376
[key: string]: any;
377
}
378
379
// Instance types
380
type CreateComponentPublicInstance<
381
P = {},
382
B = {},
383
D = {},
384
C extends ComputedOptions = {},
385
M extends MethodOptions = {},
386
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
387
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
388
PublicProps = P
389
> = ComponentPublicInstance<P, B, D, C, M, Mixin, Extends, PublicProps>;
390
391
// Emit types
392
type EmitsOptions = ObjectEmitsOptions | string[];
393
394
interface ObjectEmitsOptions {
395
[key: string]:
396
| null
397
| ((...args: any[]) => any)
398
| { (...args: any[]): any; };
399
}
400
401
// VNode types
402
type VNodeChild =
403
| VNode
404
| string
405
| number
406
| boolean
407
| null
408
| undefined
409
| VNodeArrayChildren;
410
411
type VNodeArrayChildren = Array<VNodeArrayChildren | VNodeChild>;
412
413
// Data object type
414
type Data = Record<string, unknown>;
415
```