跨平台架构区别
文章目录
- 重编译时轻运行时(uniapp)
- 轻编译时重运行时(Taro)
重编译时轻运行时(uniapp)
- 对 vue 语法直接进行编译转换成对应平台代码,再通过添加运行时代码去补充能力,比如 nextTick 实现的批量更新等运行逻辑
pages/
└── index/├── index.json // 页面配置(路由等)├── index.wxml // 模板,来自 <template>├── index.wxss // 样式,来自 <style>└── index.js // 页面逻辑,来自 <script>
优点
- 直接编程成对应平台代码,性能无限接近原生
- 编译底层带来的优化效果明显,在编译期可以做出更好的优化,比如 tree-shaking、scope hoisting、依赖提取等
缺点
- 编译时代码量大,热更新较慢
- 自由度高的高级语法纯靠编译难以实现,不如运行时灵活
- 扩展能力弱,新增功能都需要编译器支持
轻编译时重运行时(Taro)
- 利用 js 框架运行时能力,比如 Vue/React,然后针对对产出结果进行编译(比如虚拟 DOM)
- 运行时抽象 UI + 渲染器,对运行结果通过渲染器不断进行编译,类似同声翻译,而重编译时的架构类似出版社翻译
- 开发者写的是 React / Vue / JSX / Composition API 代码。这些代码都在 JS 环境中跑,不涉及平台差异。
- 根据平台不同,运行时加载不同的“渲染器”。比如把虚拟 DOM 映射为不同平台的实际 UI:
- Web:createElement() + DOM patch
- 小程序:调用 setData()、生成 WXML 节点
- React Native:调用原生控件桥接接口
- Flutter:转成 Dart Widget 结构
- 渲染器是运行时决定的,它知道怎么把“虚拟节点”变成实际平台的界面
- Taro 是把组件编译成小程序 template 模版语法然后进行递归拼接
比如:
export default function Counter() {const [count, setCount] = useState(0);return <Button onClick={() => setCount(count + 1)}>点击 {count}</Button>;
}
- useState、组件渲染等全在 JS 层运行 —— 这平台无关;
- 渲染成虚拟 DOM 树
{ type: Button, props: ..., children: ... };
- 运行时加载“小程序渲染器”,把这个虚拟 DOM:
- 转成页面 JSON 配置;
- 转成 WXML 结构;
- 调用 setData() 实际挂到页面上;
- 用户点击按钮,触发 setCount,重新触发虚拟 DOM diff → 渲染器更新 UI。
优点
- 开发者可以写 React 代码、Hooks,几乎不需要改变原有习惯
- 支持运行时逻辑更复杂的高级特性(比如 Context、Hooks 等)
- 灵活支持多框架(React/Vue/Nerv)
缺点
- 运行性能低于原生,特别是微信小程序的首次渲染性能