Vue.js 3 runtime core library providing foundational APIs for building custom renderers and managing reactive component systems
—
Vue provides several built-in components for advanced functionality including teleportation, async component loading, component caching, and transitions.
Renders content in a different location in the DOM tree while maintaining component hierarchy.
/**
* Teleport component for rendering content elsewhere in DOM
*/
const Teleport: Component<TeleportProps>;
interface TeleportProps {
/**
* Target selector or element where content should be rendered
*/
to: string | Element | null;
/**
* Whether the teleport is disabled (renders in place)
*/
disabled?: boolean;
}Usage Examples:
import { defineComponent, h, Teleport } from "@vue/runtime-core";
const ModalComponent = defineComponent({
setup() {
return () => h(Teleport,
{ to: 'body' },
h('div', { class: 'modal-overlay' }, [
h('div', { class: 'modal' }, [
h('h2', 'Modal Title'),
h('p', 'Modal content here'),
h('button', 'Close')
])
])
);
}
});
// Conditional teleport
const ConditionalTeleport = defineComponent({
props: { usePortal: Boolean },
setup(props) {
return () => h(Teleport,
{
to: '#portal-target',
disabled: !props.usePortal
},
h('div', 'Content that may be teleported')
);
}
});Handles async component loading states with fallback content.
/**
* Suspense component for handling async component loading
*/
const Suspense: Component<SuspenseProps>;
interface SuspenseProps {
/**
* Timeout in ms before showing fallback
*/
timeout?: string | number;
/**
* Whether to show fallback on first render
*/
suspensible?: boolean;
}Usage Examples:
import { defineComponent, h, Suspense, defineAsyncComponent } from "@vue/runtime-core";
const AsyncChild = defineAsyncComponent(() => import('./HeavyComponent.vue'));
const SuspenseExample = defineComponent({
setup() {
return () => h(Suspense, {
// Default slot - content to show when loaded
default: () => h(AsyncChild),
// Fallback slot - loading state
fallback: () => h('div', { class: 'loading' }, 'Loading...')
});
}
});
// With timeout
const SuspenseWithTimeout = defineComponent({
setup() {
return () => h(Suspense,
{ timeout: 3000 },
{
default: () => h(AsyncChild),
fallback: () => h('div', 'Loading with 3s timeout...')
}
);
}
});Caches inactive components to preserve state and avoid re-creation.
/**
* KeepAlive component for caching inactive components
*/
const KeepAlive: Component<KeepAliveProps>;
interface KeepAliveProps {
/**
* Components to include in caching (string, RegExp, or array)
*/
include?: MatchPattern;
/**
* Components to exclude from caching (string, RegExp, or array)
*/
exclude?: MatchPattern;
/**
* Maximum number of cached instances
*/
max?: string | number;
}
type MatchPattern = string | RegExp | (string | RegExp)[];Usage Examples:
import { defineComponent, h, KeepAlive, ref } from "@vue/runtime-core";
const TabsComponent = defineComponent({
setup() {
const currentTab = ref('tab1');
const Tab1 = defineComponent({
name: 'Tab1',
setup() {
const count = ref(0);
return () => h('div', [
h('p', `Tab 1 - Count: ${count.value}`),
h('button', { onClick: () => count.value++ }, 'Increment')
]);
}
});
const Tab2 = defineComponent({
name: 'Tab2',
setup() {
return () => h('div', 'Tab 2 Content');
}
});
return () => h('div', [
h('button', { onClick: () => currentTab.value = 'tab1' }, 'Tab 1'),
h('button', { onClick: () => currentTab.value = 'tab2' }, 'Tab 2'),
h(KeepAlive,
{ include: ['Tab1'] }, // Only cache Tab1
currentTab.value === 'tab1' ? h(Tab1) : h(Tab2)
)
]);
}
});
// With max cache limit
const KeepAliveWithMax = defineComponent({
setup() {
return () => h(KeepAlive,
{
max: 3,
include: /^Tab/ // Cache components whose names start with 'Tab'
},
// Dynamic component content
);
}
});Base component for creating custom transitions.
/**
* Base transition component for custom transitions
*/
const BaseTransition: Component<BaseTransitionProps>;
interface BaseTransitionProps {
mode?: 'in-out' | 'out-in' | 'default';
appear?: boolean;
persisted?: boolean;
// Hooks
onBeforeEnter?: (el: Element) => void;
onEnter?: (el: Element, done: () => void) => void;
onAfterEnter?: (el: Element) => void;
onEnterCancelled?: (el: Element) => void;
onBeforeLeave?: (el: Element) => void;
onLeave?: (el: Element, done: () => void) => void;
onAfterLeave?: (el: Element) => void;
onLeaveCancelled?: (el: Element) => void;
onBeforeAppear?: (el: Element) => void;
onAppear?: (el: Element, done: () => void) => void;
onAfterAppear?: (el: Element) => void;
onAppearCancelled?: (el: Element) => void;
}
/**
* Props validators for BaseTransition
*/
const BaseTransitionPropsValidators: Record<string, any>;Usage Examples:
import { defineComponent, h, BaseTransition } from "@vue/runtime-core";
const FadeTransition = defineComponent({
setup(_, { slots }) {
return () => h(BaseTransition, {
onBeforeEnter(el) {
el.style.opacity = '0';
},
onEnter(el, done) {
el.style.transition = 'opacity 0.3s';
el.style.opacity = '1';
setTimeout(done, 300);
},
onLeave(el, done) {
el.style.transition = 'opacity 0.3s';
el.style.opacity = '0';
setTimeout(done, 300);
}
}, slots.default?.());
}
});
// Usage of custom transition
const TransitionExample = defineComponent({
setup() {
const show = ref(true);
return () => h('div', [
h('button',
{ onClick: () => show.value = !show.value },
'Toggle'
),
h(FadeTransition,
show.value ? h('p', 'Fade me in/out') : null
)
]);
}
});const MultiTeleport = defineComponent({
setup() {
return () => h('div', [
h(Teleport, { to: '#header' }, h('nav', 'Navigation')),
h(Teleport, { to: '#sidebar' }, h('aside', 'Sidebar')),
h(Teleport, { to: '#footer' }, h('footer', 'Footer')),
h('main', 'Main content stays here')
]);
}
});const NestedSuspense = defineComponent({
setup() {
return () => h(Suspense, {
default: () => h('div', [
h(AsyncComponent1),
h(Suspense, {
default: () => h(AsyncComponent2),
fallback: () => h('div', 'Loading component 2...')
})
]),
fallback: () => h('div', 'Loading everything...')
});
}
});const DynamicKeepAlive = defineComponent({
setup() {
const cachedComponents = ref(['ComponentA', 'ComponentB']);
const maxCache = ref(5);
const addToCache = (name: string) => {
if (!cachedComponents.value.includes(name)) {
cachedComponents.value.push(name);
}
};
return () => h(KeepAlive, {
include: cachedComponents.value,
max: maxCache.value
}, /* dynamic component */);
}
});interface SuspenseBoundary {
vnode: VNode<RendererNode, RendererElement>;
parent: SuspenseBoundary | null;
parentComponent: ComponentInternalInstance | null;
isSVG: boolean;
container: RendererElement;
hiddenContainer: RendererElement;
anchor: RendererNode | null;
activeBranch: VNode | null;
pendingBranch: VNode | null;
deps: number;
pendingId: number;
timeout: number;
isInFallback: boolean;
isHydrating: boolean;
isUnmounted: boolean;
effects: Function[];
}
interface TransitionHooks {
mode: BaseTransitionProps['mode'];
persisted: boolean;
beforeEnter(el: Element): void;
enter(el: Element): void;
leave(el: Element, remove: () => void): void;
clone(vnode: VNode): TransitionHooks;
afterLeave?(): void;
delayLeave?(el: Element, earlyRemove: () => void, delayedLeave: () => void): void;
delayedLeave?(): void;
}
interface TransitionState {
isMounted: boolean;
isLeaving: boolean;
isUnmounting: boolean;
leavingVNodes: Map<any, VNode>;
}Install with Tessl CLI
npx tessl i tessl/npm-vue--runtime-core