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-bind/: 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-binddirective usage.
Compilation Mapping
v-bind / :: Basic attribute binding
v-bind (shorthand :) is Vue's directive for dynamically binding HTML attributes, component props, class, and style.
- Vue
<img :src="imageUrl" :class="imageCls" />
- Compiled React
<img src={imageUrl} className={imageCls} />
As the example shows, Vue's :src and :class directives are compiled into React's standard attribute syntax. VuReact adopts a direct attribute compilation strategy, converting template directives into React's JSX attributes. This fully preserves Vue's attribute binding semantics — dynamically binding variable values to element attributes.
Dynamic class and style binding
Vue supports complex class and style binding expressions. VuReact handles these complex scenarios through runtime helper functions.
Dynamic class binding
- Vue
<div :class="['card', active && 'is-active', error ? 'has-error' : '']" />
- Compiled React
import { dir } from '@vureact/runtime-core';
<div className={dir.cls(['card', active && 'is-active', error ? 'has-error' : ''])} />
Dynamic style binding
- Vue
<div :style="{ color: textColor, fontSize: size + 'px', 'background-color': bgColor }" />
- Compiled React
import { dir } from '@vureact/runtime-core';
<div style={dir.style({ color: textColor, fontSize: size + 'px', backgroundColor: bgColor })} />
As the examples show, complex class and style bindings are compiled using the dir.cls() and dir.style() helper functions. VuReact adopts a complex binding runtime processing strategy, converting Vue's complex expressions into runtime function calls. This fully preserves Vue's dynamic styling semantics.
How the runtime helper functions work:
-
dir.cls():- Handles multiple class formats including arrays, objects, and strings
- Automatically filters falsy values (
false,null,undefined,'') - Deduplicates repeated class names
- Generates the final className string
-
dir.style():- Handles object-format styles
- Automatically converts kebab-case to camelCase (
background-color→backgroundColor) - Handles values with units (automatically appends
px, etc.) - Generates a React-compatible style object
Compilation strategy details:
// Vue: :class="{ active: isActive, 'text-danger': hasError }"
// React: className={dir.cls({ active: isActive, 'text-danger': hasError })}
// Vue: :class="[isActive ? 'active' : '', errorClass]"
// React: className={dir.cls([isActive ? 'active' : '', errorClass])}
// Vue: :style="style"
// React: style={dir.style(style)}
Parameterless v-bind: Object spreading
Vue supports parameterless v-bind for spreading an entire object as element attributes.
- Vue
<Comp v-bind="props">Click</Comp>
- Compiled React
import { dir } from '@vureact/runtime-core';
<Comp {...dir.keyless(props)}>Click</Comp>
As the example shows, parameterless v-bind is compiled using the dir.keyless() helper function with the object spread syntax. VuReact adopts an object spread compilation strategy, converting Vue's object binding into React's object spread. This fully preserves Vue's object attribute binding semantics.
The role of the dir.keyless() helper function:
- Attribute conflict resolution: Handles conflicts between object properties and existing attributes
-
Special attribute conversion: Automatically converts
class→className,for→htmlFor, etc. - Style object handling: Recognizes and correctly processes style objects
-
Event handling: Identifies and converts event attributes (
@click→onClick)
Boolean attribute binding
Vue has special handling for boolean attributes, and VuReact preserves this semantics.
- Vue
<button :disabled="isLoading">Submit</button>
<input :checked="isChecked" />
<option :selected="isSelected">Option</option>
- Compiled React
<button disabled={isLoading}>Submit</button>
<input checked={isChecked} />
<option selected={isSelected}>Option</option>
Dynamic attribute name binding
Vue supports using dynamic expressions as attribute names. While not recommended, VuReact handles it correctly.
- Vue
<div :[dynamicAttr]="value">Content</div>
- Compiled React
<div {...{ [dynamicAttr]: value }}>Content</div>
Compilation strategy:
-
Computed property name: Uses the object computed property syntax
{ [key]: value } - Object spread: Applies to the element via the object spread syntax
Compilation strategy summary
VuReact's v-bind compilation strategy demonstrates a complete attribute binding conversion capability:
- Basic attribute mapping: Precisely maps Vue attribute bindings to React JSX attributes
- Complex style handling: Supports complex class and style bindings through runtime helper functions
- Object spread support: Fully supports parameterless v-bind object spread semantics
- Boolean attribute handling: Correctly handles the special behavior of boolean attributes
- Dynamic attribute names: Supports dynamic expressions as attribute names
- Component props conversion: Correctly handles props passing between components
Performance optimization strategy:
-
On-demand imports: The
dirhelper is only imported when complex bindings are used - Cache optimization: Intelligently caches the processing results of identical expressions
- Compile-time optimization: For simple expressions, generates inline logic directly
VuReact's compilation strategy ensures a smooth migration from Vue to React. Developers do not need to manually rewrite attribute binding logic. The compiled code preserves Vue's semantics and functionality while following React's attribute handling best practices, keeping the migrated application fully capable of UI presentation.
Top comments (0)