uni-app 是怎样实现一套代码多端运行的?条件编译、生命周期和分包要注意什么?

先理解原理和示例,再练习完整口述与追问。

uni-app 基于 Vue 语法,编译期把代码转换为各平台产物:小程序端编译为 WXML/WXSS 和对应 JS,H5 端是普通 Vue 应用,App 端由 WebView 或原生渲染(nvue、uvue)承载。平台差异用 #ifdef/#ifndef 条件编译处理。生命周期分应用(onLaunch、onShow)、页面(onLoad、onShow、onReady、onPullDownRefresh)和组件三层。主包有体积限制,需用 subPackages 分包与预下载。

小程序的逻辑层和渲染层分离运行,uni-app 在编译期把模板转换为小程序模板,运行时把 Vue 的响应式数据变更通过 setData 同步到渲染层,因此一次性传输大量数据会卡顿。uni.request、uni.navigateTo 等 API 在各端映射到对应平台能力;尺寸单位 rpx 以 750 宽为基准,按屏幕宽度换算。

条件编译写在注释中,编译到某个平台时只保留匹配的代码,JS、模板、样式和 pages.json 都支持。页面生命周期中,onLoad 只执行一次并接收参数,onShow 每次显示都执行;Vue 组件的 mounted 与页面的 onReady 时机不同。微信小程序主包限制 2MB,整个项目总包限制会随官方规则调整,分包后非首屏页面放入子包,preloadRule 可在进入某页时预下载。

js
// #ifdef MP-WEIXIN
wx.login({ success: ({ code }) => loginByCode(code) })
// #endif
// #ifdef H5
location.href = buildOAuthUrl()
// #endif
json
{
  "subPackages": [{ "root": "pages-order", "pages": [{ "path": "detail/index" }] }],
  "preloadRule": { "pages/index/index": { "network": "all", "packages": ["pages-order"] } }
}

H5 端可用的 DOM API(document、window)在小程序端不存在;页面栈层级有上限(微信为 10 层),深层跳转应使用 redirectTo;频繁 setData 大对象是小程序卡顿的主要原因。

uni-app 用 Vue 语法开发,编译时转换成各平台的代码:小程序端转成小程序模板,数据变化通过 setData 同步到渲染层;H5 是普通 Vue 应用;App 端用 WebView 或原生渲染。平台差异用 #ifdef 条件编译。生命周期要区分应用、页面和组件,onLoad 只执行一次拿参数,onShow 每次显示都会执行。主包有 2MB 限制,要用 subPackages 分包加预下载,也要控制 setData 的数据量。