六维教程

uni-app 条件编译

这是 uni-app 最核心、也最容易被新手忽略的知识点。条件编译,一套代码里针对不同平台写不同代码,编译时只保留当前平台的部分。

一句话理解,代码里标记 #ifdef H5 的片段只会在编译 H5 端时存在,其他端会被直接删除,编译产物里根本看不到。

为什么需要条件编译

uni-app 已经封装了绝大多数跨端能力,但平台差异永远存在,典型场景:

  • H5 端能用的网页能力(如键盘事件、localStorage),小程序里没有
  • App 端能调用的原生能力(如推送、本地通知),网页里没有
  • 微信小程序的分享、订阅消息,其他平台没有
  • 同一功能各端 API 不同(如登录授权方式)

处理这些差异,不要试图用一套逻辑硬兼容所有端,条件编译是解决差异化最有效的手段,只在需要的地方为特定平台写专属代码。

平台标识速查

平台标识 对应平台
H5 网页端
APP-PLUS App(iOS、Android、鸿蒙)
MP-WEIXIN 微信小程序
MP-ALIPAY 支付宝小程序
MP-BAIDU 百度小程序
MP-TOUTIAO 抖音小程序
MP-QQ QQ 小程序
MP 所有小程序平台
VUE3 Vue3 编译版本

记住最常用的三个就够起步了,H5APP-PLUSMP-WEIXIN

三种语句

语句 含义
#ifdef 仅在该平台存在时编译
#ifndef 该平台不存在时编译
#endif 结束条件编译

两个平台同时满足用 ||,同时满足用 &&

// 微信 或 支付宝 小程序都编译
// #ifdef MP-WEIXIN || MP-ALIPAY
// #endif

在 JS 中使用

注释语法,// 开头:

// #ifdef H5
console.log('这段代码只会在网页端编译')
// #endif

// #ifdef APP-PLUS
console.log('这段代码只会在 App 端编译')
// #endif

// #ifndef H5
console.log('非网页端都会编译这段(小程序、App 等)')
// #endif

实战例子,在 App 端调用原生功能,网页端给提示:

function shareToFriend() {
  // #ifdef APP-PLUS
  plus.share.sendWithSystem({
    content: '分享内容',
    success() {}
  })
  // #endif

  // #ifndef APP-PLUS
  uni.showToast({ title: '当前平台不支持分享', icon: 'none' })
  // #endif
}

在模板中使用

HTML 注释语法,<!-- -->

<template>
  <view class="page">
    <!-- #ifdef H5 -->
    <view class="web-tip">网页端专属提示</view>
    <!-- #endif -->

    <!-- #ifdef MP-WEIXIN -->
    <button open-type="share">分享给微信好友</button>
    <!-- #endif -->
  </view>
</template>

微信小程序端打包后,页面里只有分享按钮,没有网页提示;H5 端正好相反。

在样式中使用

CSS 注释语法,/* */

.container {
  padding: 20rpx;
}

/* #ifdef H5 */
.container {
  max-width: 600px;  /* 网页端限制最大宽度,居中显示 */
  margin: 0 auto;
}
/* #endif */

同一条规则写两遍也没问题,编译时会把不属于当前平台的块整个删掉。

在 pages.json 中使用

配置文件里同样支持,注意这里用的是普通注释写法:

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页"
        // #ifdef APP-PLUS
        ,"navigationBarBackgroundColor": "#FF0000"
        // #endif
      }
    }
  ]
}

提示:在 pages.json 里用条件编译时,要注意 JSON 的逗号位置,容易写成语法错误,不熟练时建议尽量少在配置里用。

按平台拆分文件

除了在文件内部做条件编译,还可以整个文件按平台拆分。文件名带平台后缀,编译到对应平台时优先使用:

pages/
├── login/
│   ├── login.vue          # 通用登录页
│   ├── login-h5.vue       # 网页端专用(编译 H5 时替换 login.vue)
│   └── login-mp-weixin.vue # 微信小程序专用

适合平台差异特别大的页面,比如登录方式完全不同的场景。能拆文件就不写一堆 #ifdef,可读性更好。

常见误区

误区一:条件编译可以随意嵌套

每个 #ifdef 必须配一个 #endif,注释必须完整,嵌套时要小心层级,写错会编译报错或者代码莫名消失。

误区二:把业务判断写成条件编译

条件编译是编译期处理,用户运行时代码已经定死。if 判断是运行期处理,用户还能动态改变。到底部选项卡显示哪个、用户有没有登录,这些必须用 if,不是条件编译。

误区三:以为条件编译能替代 API 适配

条件编译只解决「这段代码属于哪个平台」,平台共有的能力直接用 uni. API 让框架处理,不要到处 #ifdef,能不用就不用的代码最干净。

综合示例:一个方法适配三端

做一个「提醒用户」功能,App 端弹原生通知,微信小程序弹确认框,网页端直接提示:

function remind(message) {
  // #ifdef APP-PLUS
  plus.push.createMessage(message, 'notice', { title: '待办提醒' })
  // #endif

  // #ifdef MP-WEIXIN
  uni.showModal({
    title: '提醒',
    content: message,
    showCancel: false
  })
  // #endif

  // #ifdef H5
  uni.showToast({ title: message, icon: 'none' })
  // #endif
}

三个平台打包后,各自只会留下对应的一段代码,另一个平台的人根本不会看到别的端逻辑。

总结

知识点 要点
为什么需要 平台差异客观存在,条件编译是解决差异化的最有效手段
平台标识 H5、APP-PLUS、MP-WEIXIN 最常用
语句 #ifdef 存在时编译 / #ifndef 不存在时编译 / #endif 结束
使用位置 JS(//)、模板(<!-- -->)、CSS(/* */)、pages.json
文件级拆分 login-h5.vue 这种带平台后缀的文件
常见误区 不是运行时判断,不能乱嵌套,能不用就不用

一句话总结:条件编译是 uni-app 处理平台差异的终极武器,用注释标记代码归属,编译时各取所需,不要在业务逻辑里硬兼容所有平台,分不开的才交给条件编译。

上一篇
uni-app 网络请求
下一篇
uni-app 生命周期