VuReact is a compiler for migrating from Vue to React — and for writing React with Vue syntax. In this article, we dive straight into the core: how Vue's common v-slot directive is compiled into React code by VuReact.
Before We Start
To keep the examples easy to read, this article follows two simple conventions:
- All Vue and React snippets focus on core logic only, with full component wrappers and unrelated configuration omitted.
- The discussion assumes you are already familiar with Vue 3's
v-slotdirective usage.
Compilation Mapping
v-slot / #: Basic slot usage
v-slot (shorthand #) is Vue's directive for defining and using slots, enabling content distribution and reuse in components.
Default slot
- Vue
<!-- Parent component -->
<MyComponent>
<template #default>
<p>Default slot content</p>
</template>
</MyComponent>
<!-- Or shorthand -->
<MyComponent>
<p>Default slot content</p>
</MyComponent>
- Compiled React
// Parent component
<MyComponent>
<p>Default slot content</p>
</MyComponent>
As the example shows, Vue's default slot is directly compiled into React's children. VuReact adopts a children compilation strategy, converting template slots into React's standard children passing mechanism. This fully preserves Vue's default slot semantics — passing content as child elements to the component.
The key characteristics of this compilation approach are:
- Semantic consistency: Fully simulates Vue's default slot behavior by implementing content distribution
- React-native support: Uses React's standard children mechanism with no additional adaptation needed
-
Simplified syntax: Vue's
<template #default>is simplified to directly passing child elements - Performance optimization: Uses React's native mechanism directly with zero runtime overhead
Named slots
Vue supports multiple named slots for more flexible content distribution.
Basic named slots
- Vue
<!-- Parent component -->
<Layout>
<template #header>
<h1>Page Title</h1>
</template>
<template #main>
<p>Main content area</p>
</template>
<template #footer>
<p>Footer information</p>
</template>
</Layout>
- Compiled React
// Parent component
<Layout
header={<h1>Page Title</h1>}
main={<p>Main content area</p>}
footer={<p>Footer information</p>}
/>
As the example shows, Vue's named slots are compiled into React props. VuReact adopts a props compilation strategy, converting named slots into component props. This fully preserves Vue's named slot semantics — distinguishing different slot content through different prop names.
Scoped slots
Vue's scoped slots allow child components to pass data back to parent components, enabling more flexible render control.
Basic scoped slots
- Vue
<!-- Parent component -->
<DataList :items="users">
<template #item="slotProps">
<div class="user-item">
<span>{{ slotProps.user.name }}</span>
<span>{{ slotProps.user.age }} years old</span>
</div>
</template>
</DataList>
<!-- Child component DataList.vue -->
<template>
<ul>
<li v-for="item in props.items" :key="item.id">
<slot name="item" :user="item"></slot>
</li>
</ul>
</template>
- Compiled React
// Parent component
<DataList
items={users}
item={(slotProps) => (
<div className="user-item">
<span>{slotProps.user.name}</span>
<span>{slotProps.user.age} years old</span>
</div>
)}
/>
// Child component DataList.jsx
function DataList(props) {
return (
<ul>
{props.items.map((itemData) => (
<li key={itemData.id}>
{props.item?.({ user: itemData })}
</li>
))}
</ul>
);
}
As the example shows, Vue's scoped slots are compiled into React function props. VuReact adopts a function props compilation strategy, converting scoped slots into function props that receive parameters. This fully preserves Vue's scoped slot semantics — the child component passes data to the parent through function calls, and the parent receives data and renders via function parameters.
Dynamic slot names
Vue supports dynamic slot names for more flexible slot selection.
- Vue
<BaseLayout>
<template #[dynamicSlotName]>
Dynamic slot content
</template>
</BaseLayout>
- Compiled React
<BaseLayout
{...{ [dynamicSlotName]: "Dynamic slot content" }}
/>
Compilation strategy:
-
Computed property name: Uses the object computed property syntax
{ [key]: value } - Object spread: Applies to the component via the object spread syntax
- Runtime processing: Dynamic slot names need to be determined at runtime
Slot fallback content
Vue supports providing default content in slot definitions, displayed when the parent component does not provide slot content.
- Vue
<!-- Child component Button.vue -->
<template>
<button class="btn">
<slot>
<span>Default button text</span>
</slot>
</button>
</template>
- Compiled React
// Child component Button.jsx
function Button(props) {
return (
<button className="btn">
{props.children || <span>Default button text</span>}
</button>
);
}
Fallback content handling rules:
- children check: Checks whether children exists
- Default value rendering: Renders fallback content when children is falsy
- React compatible: Uses React's standard conditional rendering pattern
Compilation strategy summary
VuReact's v-slot compilation strategy demonstrates a complete slot system conversion capability:
- Default slots: Converted to React's children
- Named slots: Converted to component props
- Scoped slots: Converted to function props
- Dynamic slots: Supports dynamic slot names
- Fallback content: Supports slot default content
Slot type mapping table:
| Vue slot type | React equivalent | Description |
|---|---|---|
| Default slot | children |
As child elements of the component |
| Named slot | prop |
As a property of the component |
| Scoped slot | function prop |
As a function property that receives parameters |
| Dynamic slot | computed property |
Uses object computed property syntax |
Performance optimization strategy:
- Static slot optimization: Static slot content is compiled into static JSX
- Function caching: For scoped slots, render functions are intelligently cached
- On-demand generation: The most minimal code is generated based on actual usage
- Type inference: Slot type definitions are intelligently inferred
VuReact's compilation strategy ensures a smooth migration from Vue to React. Developers do not need to manually rewrite slot logic. The compiled code preserves Vue's semantics and flexibility while following React's component design patterns, keeping the migrated application fully capable of content distribution.
Top comments (0)