uni-app能实现一套代码、多端运行,核心是通过编译器 + 运行时实现的:
- 编译器:将
uni-app统一代码编译生成每个平台支持的特有代码;如在小程序平台,编译器将.vue文件拆分生成wxml、wxss、js等代码。 - 运行时:动态处理数据绑定、事件代理,保证Vue和平台宿主数据的一致性;
uni-app项目根据所依赖的Vue版本不同,编译器的实现也不同:
- vue2:
uni-app编译器基于wepback实现 - vue3:
uni-app编译器基于Vite实现,编译速度更快
条件编译处理多端差异 #
uni-app 已将常用的组件、API封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。
但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。
- 大量写 if else,会造成代码执行性能低下和管理混乱。
- 编译到不同的工程后二次修改,会让后续升级变的很麻烦。
- 为每个平台重写,明明主业务逻辑又一样
在 C 语言中,通过 #ifdef、#ifndef 的方式,为 Windows、Mac 等不同 OS 编译不同的代码。
uni-app 团队参考这个思路,为 uni-app 提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。
使用方式 #
以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。
#ifdef:if defined 仅在某平台存在#ifndef:if not defined 除了某平台均存在%PLATFORM%:平台名称
#ifdef APP-PLUS
仅出现在 App 平台下的代码
#endif
#ifndef H5
除了 H5 平台,其它平台均存在的代码(注意if后面有个n)
#endif
#ifdef H5 || MP-WEIXIN
在 H5 平台或微信小程序平台存在的代码
#endif
%PLATFORM% 可取值如下
| 值 | 生效条件 | 版本支持 |
|---|---|---|
| VUE3 | uni-app js引擎版用于区分vue2和3 | HBuilderX 3.2.0+ |
| VUE2 | uni-app js引擎版用于区分vue2和3 | |
| UNI-APP-X | 用于区分是否是uni-app x项目 | HBuilderX 3.9.0+ |
| uniVersion | 用于区分编译器的版本 | HBuilderX 3.9.0+ |
| APP | App | |
| APP-PLUS | uni-app js引擎版编译为App时 | |
| APP-PLUS-NVUE或APP-NVUE | App nvue 页面 | |
| APP-ANDROID | App Android 平台 | |
| APP-IOS | App iOS 平台 | |
| APP-HARMONY | App HarmonyOS Next 平台 | |
| H5 | H5(推荐使用 WEB) |
|
| WEB | web(同H5) |
HBuilderX 3.6.3+ |
| MP-WEIXIN | 微信小程序 | |
| MP-ALIPAY | 支付宝小程序 | |
| MP-BAIDU | 百度小程序 | |
| MP-TOUTIAO | 抖音小程序 | |
| MP-LARK | 飞书小程序 | |
| MP-QQ | QQ小程序 | |
| MP-KUAISHOU | 快手小程序 | |
| MP-JD | 京东小程序 | |
| MP-360 | 360小程序 | |
| MP-HARMONY | 鸿蒙元服务 | HBuilderX 4.34+ |
| MP-XHS | 小红书小程序 | |
| MP | 微信小程序/支付宝小程序/百度小程序/抖音小程序/飞书小程序/QQ小程序/360小程序/鸿蒙元服务 | |
| QUICKAPP-WEBVIEW | 快应用通用(包含联盟、华为) | |
| QUICKAPP-WEBVIEW-UNION | 快应用联盟 | |
| QUICKAPP-WEBVIEW-HUAWEI | 快应用华为 |
注意:
- 条件编译是利用注释实现的,在不同语法里注释写法不一样,js/uts使用
// 注释、css 使用/* 注释 */、vue/nvue/uvue 模板里使用<!-- 注释 -->; - 条件编译APP-PLUS包含APP-NVUE和APP-VUE,APP-PLUS-NVUE和APP-NVUE没什么区别,为了简写后面出了APP-NVUE ;
- 对于未定义平台名称,可能是名称写错了,也可能是低版本HBuilderX还不认识这个平台。此时的条件编译,
#ifdef中的代码不会生效,而#ifndef中的代码会生效; - 使用条件编译请保证
编译前和编译后文件的语法正确性,即要保障无论条件编译是否生效都能通过语法校验。比如:json文件中不能有多余的逗号,js中不能重复导入;
{
"key": "a"
// #ifdef MP-WEIXIN
,"key": "b"
// #endif
}
// #ifdef MP-WEIXIN
import a as aWx from 'a/wx'
// #endif
// #ifndef MP-WEIXIN
import a as aIndex from 'a/index'
// #endif
var a
// #ifdef MP-WEIXIN
a = aWx
// #endif
// #ifndef MP-WEIXIN
a = aIndex
// #endif