# 实现一套代码在多端有不同表现

在小程序中展示 A 内容或者执行 A 逻辑,但在 APP 中展示 B 内容或者执行 B 逻辑。

这种情况就属于条件需求:针对不同的设备和运行环境,预期完成不同的逻辑和页面显示。

为了支持跨端项目不同平台有不同呈现/逻辑的需求,多端框架支持条件编译语法。

  1. 目前支持 wxmlwxssjs/tsjsonless/sasswxss 等文件类型,资源支持通过配置区分不同平台。
  2. json 文件支持的标记:mini-wechat(微信小程序)、mini-android(安卓 APP)、mini-ios(苹果 APP)。
  3. wxmljsless/wxss 内置的标记: ANDROIDIOSMPNATIVE(Android 或 iOS)。
  4. 支持 || 语法表示同时兼容多种条件,如 <!-- #if MP || ANDROID -->(json 不支持该写法)。
  5. 条件编译采用注释语法,通过不同的条件编译不同的内容到不同的平台产物中。

接下来简单演示一下如何开启条件编译,以及分别演示各个文件如何编写条件规则。

# 一、开启条件编译

在小程序开发者工具中「详情-本地设置-启用条件编译」,开启后项目在运行或者编译时会自动根据编写条件区分内容。

# 二、编写演示

所有文件基本都遵循下列原则:

  1. 如果标记没有#if #endif 闭环,则会报错 error:#if without #endif

  2. 在一个条件组中,编译只会取第一个匹配到的内容

  3. NATIVEIOS || ANDROID 等效(JSON 文件不适用)

# 2.1 WXML 文件

<!-- #if MP -->
<view>小程序展示的信息</view>
<!-- #elif IOS || ANDROID -->
<view>APP展示的信息(包含 iOS 和 Android)</view>
<!-- #endif -->


<!-- #elif MP -->
<view>小程序展示的信息</view>
<!-- #elif NATIVE -->
<view>NATIVE和IOS || ANDROID等效,在 iOS 和 Android 中显示</view>
<!-- #endif -->


<!-- #if MP -->
<view>小程序展示的信息</view>
<!-- #elif IOS -->
<view>iOS 匹配到这里就展示,下面 NATIVE 不会展示</view>
<!-- #elif NATIVE -->
<view>因为 iOS 上面匹配了,所以这里只在 Android 中显示</view>
<!-- #endif -->


<!-- #if MP -->
<view>小程序展示的信息</view>
<!-- #elif NATIVE -->
<view>在 iOS 和 Android 中显示</view>
<!-- #elif IOS -->
<view>因为上面 NATIVE 已经匹配了,这里不可能展示出来</view>
<!-- #endif -->


<!-- #if ANDROID -->
<view>只有安卓展示的信息</view>
<!-- #endif -->

# 2.2 WXSS 文件(css/sass/less 适用)

wxss 的编译条件可以在样式括号内,也可以在外层。

.test-view{
  /* #if MP */
  color: red;
  /* #elif IOS */
  color: green;
  /* #elif ANDROID */
  color: yellow;
  /* #endif */


  /* #if MP || ANDROID */
  background-color: black;
  /* #endif */
}

/* #if MP */
.top{
    position: fixed;
}
/* #endif */

# 2.3 JS 文件(TS 适用)

// #if MP
console.log('只在微信小程序执行')
// #elif IOS
console.log('只在 iOS 执行')
// #elif ANDROID
console.log('只在 Android 执行')
// #endif

// #if MP
console.log('只在微信小程序执行')
// #elif NATIVE
console.log('只在 iOS 和 Android 执行')
// #elif ANDROID
console.log('因为上面 NATIVE 已经匹配了,这里不可能执行')
// #endif


// #if MP || IOS
console.log('在微信小程序和 iOS 执行')
// #endif

需要注意,js 和 ts 的条件包含需要是完整的执行体,而不可直接拆分代码行,下图这种例子是不支持的,如果你觉得冗余,建议封装为函数。

# 2.4 JSON 文件

在项目中只针对 app.json 和 页面的 json 有效,在特定的 mini-wechat 、 mini-ios、mini-android 里的内容将在编译运行时,覆盖原来的。

{
    "window": {
        "navigationBarTitleText": "Weixin",
    },
    "mini-wechat": {
        "window": {
            "navigationBarTitleText": "wechat demo"
        }
    },
    "mini-ios": {
        "window": {
            "navigationBarTitleText": "iOS demo"
        }
    },
    "mini-android": {
        "window": {
            "navigationBarTitleText": "android demo"
        }
    }
}

# 三、资源差异打包

在 app.json 中配置 static 字段,指定每个目录/文件只能发布到特定的平台。

比如下面例子,表示 miniprogram/pages/logs 目录下的所有文件,只在 iOS APP 编译时被打包,其他平台不会包含。

{
    "static": [
        {
            "pattern": "miniprogram/pages/logs/*", // 支持glob语法
            "platforms": ['mini-ios']
        }
    ]
}