VuReact 1.9.0 发布,一套面向 Vue 迁移 React 的编译工具
VuReact 已于近日完成对 Vue 3.4+ defineModel 宏的完整编译支持。开发者现在可以在 Vue 源码中直接使用 defineModel 声明 v-model 双向绑定,VuReact 会将其编译为标准、可维护的 React 代码。 defineModel 是 Vue 3.4 中正式发布的编译器宏,用于简化 v-model 双向绑定的声明。VuReact 将其编译为 useVRef + useUpdated 的组合:useVRef 将 prop 值转为响应式 ref,useUpdated 在值变化时自动触发 onUpdate:xxx 回调通知父组件。组件内直接修改 .value 即可触发父组件更新,与 Vue 开发体验完全一致。 代码示例: Vue 源码(使用 defineModel): <script setup lang="ts">// 声明 "state" prop,由父组件通过 v-model:state 使用const state = defineModel<string>('state'); // 声明带选项的 "modelValue" prop,由父组件通过 v-model 使用const modelValue = defineModel({ default: 'xxx' }); // 声明带选项的 "count" prop,由父组件通过 v-model:count 使用const count = defineModel<number>('count', { type: Number, default: 0, required: true, }); const update = () => { state.value = 'hello'; count.value++; }; </script> <template><input v-model="modelValue" /><div>Parent bound v-model is: {{ count }}</div><button @click="update">Increment</button></template> VuReact 编译后的 React 产物: import { useCallback, memo } from 'react'; import { useVRef, useUpdated } from '@vureact/runtime-core'; export type IChildProps = { state?: string; modelValue?: string; count: number; } & { onUpdateState?: (arg: string) => void; onUpdateModelValue?: (arg: string) => void; onUpdateCount?: (arg: number) => void; }; const Child = memo((props: IChildProps) => { const state = useVRef<string>(props.state); const modelValue = useVRef<string>(props.modelValue ?? 'xxx'); const count = useVRef<number>(props.count ?? 0); const update = useCallback(() => { state.value = 'hello'; count.value++; }, [state.value, count.value]); useUpdated(() => { props.onUpdateState?.(state.value); }, [state.value]); useUpdated(() => { props.onUpdateModelValue?.(modelValue.value); }, [modelValue.value]); useUpdated(() => { props.onUpdateCount?.(count.value); }, [count.value]); return ( <> <input value={modelValue} onChange={(e) => { modelValue.value = e.target.value; }} /> <div>Parent bound v-model is:{count.value}</div> <button onClick={update}>Increment</button> </> ); }); export default Child; 从示例可以看到:Vue 的 defineModel 被分解为三部分 —— prop 类型声明与事件回调声明被映射到 IChildProps 类型中,运行时响应式通过 useVRef + useUpdated 实现。模板中的 v-model 则被编译为 React 受控组件的 value + onChange 模式。 本次支持的 defineModel 能力包括: 基础双向绑定:defineModel<string>() 编译为 prop 类型声明 + onUpdateXxx 事件回调 + useVRef 运行时响应式 自定义 prop 名称:defineModel<string>('state') 支持指定 prop 名称,父组件通过 v-model:state 使用 类型与默认值:支持 type、default、required 选项,required: true 在类型定义中转为必填,default 通过 ?? 空值合并实现 模板 v-model 绑定:编译为 React 受控组件的 value + onChange 模式 暂不支持的 defineModel 用法: 返回值数组解构(Vue 3.4+ 实验特性):const [model, modifiers] = defineModel() get / set 自定义存取器 validator 验证函数 上述不支持的场景,建议使用标准 defineModel 写法或直接使用 useVRef 自行实现自定义逻辑。 VuReact 是一套面向 Vue 迁移 React 与混合开发的完整解决方案,将 Vue 3 SFCs・Scripts・Styles 完整转为纯 React(非运行时桥接)组件的 AST 编译器,采用语义级编译路线,产物为纯 React 代码,不依赖 Vue 运行时。目前已完成 defineProps、defineEmits、defineExpose、defineModel 等核心宏的语义映射,以及 ref、computed、watch、scoped style 等 Vue 特性的完整适配。 详情可查阅: VuReact GitHub:https://github.com/vureact-js/core(欢迎 Star ⭐~开源不易) defineModel 编译对照:https://vureact.top/guide/semantic-comparison/script/define-model.html