0
# Built-in Components
1
2
Vue provides several built-in components for advanced functionality including teleportation, async component loading, component caching, and transitions.
3
4
## Capabilities
5
6
### Teleport Component
7
8
Renders content in a different location in the DOM tree while maintaining component hierarchy.
9
10
```typescript { .api }
11
/**
12
* Teleport component for rendering content elsewhere in DOM
13
*/
14
const Teleport: Component<TeleportProps>;
15
16
interface TeleportProps {
17
/**
18
* Target selector or element where content should be rendered
19
*/
20
to: string | Element | null;
21
22
/**
23
* Whether the teleport is disabled (renders in place)
24
*/
25
disabled?: boolean;
26
}
27
```
28
29
**Usage Examples:**
30
31
```typescript
32
import { defineComponent, h, Teleport } from "@vue/runtime-core";
33
34
const ModalComponent = defineComponent({
35
setup() {
36
return () => h(Teleport,
37
{ to: 'body' },
38
h('div', { class: 'modal-overlay' }, [
39
h('div', { class: 'modal' }, [
40
h('h2', 'Modal Title'),
41
h('p', 'Modal content here'),
42
h('button', 'Close')
43
])
44
])
45
);
46
}
47
});
48
49
// Conditional teleport
50
const ConditionalTeleport = defineComponent({
51
props: { usePortal: Boolean },
52
setup(props) {
53
return () => h(Teleport,
54
{
55
to: '#portal-target',
56
disabled: !props.usePortal
57
},
58
h('div', 'Content that may be teleported')
59
);
60
}
61
});
62
```
63
64
### Suspense Component
65
66
Handles async component loading states with fallback content.
67
68
```typescript { .api }
69
/**
70
* Suspense component for handling async component loading
71
*/
72
const Suspense: Component<SuspenseProps>;
73
74
interface SuspenseProps {
75
/**
76
* Timeout in ms before showing fallback
77
*/
78
timeout?: string | number;
79
80
/**
81
* Whether to show fallback on first render
82
*/
83
suspensible?: boolean;
84
}
85
```
86
87
**Usage Examples:**
88
89
```typescript
90
import { defineComponent, h, Suspense, defineAsyncComponent } from "@vue/runtime-core";
91
92
const AsyncChild = defineAsyncComponent(() => import('./HeavyComponent.vue'));
93
94
const SuspenseExample = defineComponent({
95
setup() {
96
return () => h(Suspense, {
97
// Default slot - content to show when loaded
98
default: () => h(AsyncChild),
99
100
// Fallback slot - loading state
101
fallback: () => h('div', { class: 'loading' }, 'Loading...')
102
});
103
}
104
});
105
106
// With timeout
107
const SuspenseWithTimeout = defineComponent({
108
setup() {
109
return () => h(Suspense,
110
{ timeout: 3000 },
111
{
112
default: () => h(AsyncChild),
113
fallback: () => h('div', 'Loading with 3s timeout...')
114
}
115
);
116
}
117
});
118
```
119
120
### KeepAlive Component
121
122
Caches inactive components to preserve state and avoid re-creation.
123
124
```typescript { .api }
125
/**
126
* KeepAlive component for caching inactive components
127
*/
128
const KeepAlive: Component<KeepAliveProps>;
129
130
interface KeepAliveProps {
131
/**
132
* Components to include in caching (string, RegExp, or array)
133
*/
134
include?: MatchPattern;
135
136
/**
137
* Components to exclude from caching (string, RegExp, or array)
138
*/
139
exclude?: MatchPattern;
140
141
/**
142
* Maximum number of cached instances
143
*/
144
max?: string | number;
145
}
146
147
type MatchPattern = string | RegExp | (string | RegExp)[];
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
import { defineComponent, h, KeepAlive, ref } from "@vue/runtime-core";
154
155
const TabsComponent = defineComponent({
156
setup() {
157
const currentTab = ref('tab1');
158
159
const Tab1 = defineComponent({
160
name: 'Tab1',
161
setup() {
162
const count = ref(0);
163
return () => h('div', [
164
h('p', `Tab 1 - Count: ${count.value}`),
165
h('button', { onClick: () => count.value++ }, 'Increment')
166
]);
167
}
168
});
169
170
const Tab2 = defineComponent({
171
name: 'Tab2',
172
setup() {
173
return () => h('div', 'Tab 2 Content');
174
}
175
});
176
177
return () => h('div', [
178
h('button', { onClick: () => currentTab.value = 'tab1' }, 'Tab 1'),
179
h('button', { onClick: () => currentTab.value = 'tab2' }, 'Tab 2'),
180
181
h(KeepAlive,
182
{ include: ['Tab1'] }, // Only cache Tab1
183
currentTab.value === 'tab1' ? h(Tab1) : h(Tab2)
184
)
185
]);
186
}
187
});
188
189
// With max cache limit
190
const KeepAliveWithMax = defineComponent({
191
setup() {
192
return () => h(KeepAlive,
193
{
194
max: 3,
195
include: /^Tab/ // Cache components whose names start with 'Tab'
196
},
197
// Dynamic component content
198
);
199
}
200
});
201
```
202
203
### BaseTransition Component
204
205
Base component for creating custom transitions.
206
207
```typescript { .api }
208
/**
209
* Base transition component for custom transitions
210
*/
211
const BaseTransition: Component<BaseTransitionProps>;
212
213
interface BaseTransitionProps {
214
mode?: 'in-out' | 'out-in' | 'default';
215
appear?: boolean;
216
persisted?: boolean;
217
218
// Hooks
219
onBeforeEnter?: (el: Element) => void;
220
onEnter?: (el: Element, done: () => void) => void;
221
onAfterEnter?: (el: Element) => void;
222
onEnterCancelled?: (el: Element) => void;
223
224
onBeforeLeave?: (el: Element) => void;
225
onLeave?: (el: Element, done: () => void) => void;
226
onAfterLeave?: (el: Element) => void;
227
onLeaveCancelled?: (el: Element) => void;
228
229
onBeforeAppear?: (el: Element) => void;
230
onAppear?: (el: Element, done: () => void) => void;
231
onAfterAppear?: (el: Element) => void;
232
onAppearCancelled?: (el: Element) => void;
233
}
234
235
/**
236
* Props validators for BaseTransition
237
*/
238
const BaseTransitionPropsValidators: Record<string, any>;
239
```
240
241
**Usage Examples:**
242
243
```typescript
244
import { defineComponent, h, BaseTransition } from "@vue/runtime-core";
245
246
const FadeTransition = defineComponent({
247
setup(_, { slots }) {
248
return () => h(BaseTransition, {
249
onBeforeEnter(el) {
250
el.style.opacity = '0';
251
},
252
253
onEnter(el, done) {
254
el.style.transition = 'opacity 0.3s';
255
el.style.opacity = '1';
256
setTimeout(done, 300);
257
},
258
259
onLeave(el, done) {
260
el.style.transition = 'opacity 0.3s';
261
el.style.opacity = '0';
262
setTimeout(done, 300);
263
}
264
}, slots.default?.());
265
}
266
});
267
268
// Usage of custom transition
269
const TransitionExample = defineComponent({
270
setup() {
271
const show = ref(true);
272
273
return () => h('div', [
274
h('button',
275
{ onClick: () => show.value = !show.value },
276
'Toggle'
277
),
278
h(FadeTransition,
279
show.value ? h('p', 'Fade me in/out') : null
280
)
281
]);
282
}
283
});
284
```
285
286
## Advanced Usage
287
288
### Multiple Teleports
289
290
```typescript
291
const MultiTeleport = defineComponent({
292
setup() {
293
return () => h('div', [
294
h(Teleport, { to: '#header' }, h('nav', 'Navigation')),
295
h(Teleport, { to: '#sidebar' }, h('aside', 'Sidebar')),
296
h(Teleport, { to: '#footer' }, h('footer', 'Footer')),
297
h('main', 'Main content stays here')
298
]);
299
}
300
});
301
```
302
303
### Nested Suspense
304
305
```typescript
306
const NestedSuspense = defineComponent({
307
setup() {
308
return () => h(Suspense, {
309
default: () => h('div', [
310
h(AsyncComponent1),
311
h(Suspense, {
312
default: () => h(AsyncComponent2),
313
fallback: () => h('div', 'Loading component 2...')
314
})
315
]),
316
fallback: () => h('div', 'Loading everything...')
317
});
318
}
319
});
320
```
321
322
### Dynamic KeepAlive Patterns
323
324
```typescript
325
const DynamicKeepAlive = defineComponent({
326
setup() {
327
const cachedComponents = ref(['ComponentA', 'ComponentB']);
328
const maxCache = ref(5);
329
330
const addToCache = (name: string) => {
331
if (!cachedComponents.value.includes(name)) {
332
cachedComponents.value.push(name);
333
}
334
};
335
336
return () => h(KeepAlive, {
337
include: cachedComponents.value,
338
max: maxCache.value
339
}, /* dynamic component */);
340
}
341
});
342
```
343
344
## Types
345
346
```typescript { .api }
347
interface SuspenseBoundary {
348
vnode: VNode<RendererNode, RendererElement>;
349
parent: SuspenseBoundary | null;
350
parentComponent: ComponentInternalInstance | null;
351
isSVG: boolean;
352
container: RendererElement;
353
hiddenContainer: RendererElement;
354
anchor: RendererNode | null;
355
activeBranch: VNode | null;
356
pendingBranch: VNode | null;
357
deps: number;
358
pendingId: number;
359
timeout: number;
360
isInFallback: boolean;
361
isHydrating: boolean;
362
isUnmounted: boolean;
363
effects: Function[];
364
}
365
366
interface TransitionHooks {
367
mode: BaseTransitionProps['mode'];
368
persisted: boolean;
369
beforeEnter(el: Element): void;
370
enter(el: Element): void;
371
leave(el: Element, remove: () => void): void;
372
clone(vnode: VNode): TransitionHooks;
373
afterLeave?(): void;
374
delayLeave?(el: Element, earlyRemove: () => void, delayedLeave: () => void): void;
375
delayedLeave?(): void;
376
}
377
378
interface TransitionState {
379
isMounted: boolean;
380
isLeaving: boolean;
381
isUnmounting: boolean;
382
leavingVNodes: Map<any, VNode>;
383
}
384
```