uni-app 條件編譯

小陳的筆記發表於2022-06-16

跨端相容

uni-app 已將常用的元件、JS 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
需條件編譯的程式碼
#endif
僅出現在 App 平臺下的程式碼
#ifndef  H5
需條件編譯的程式碼
#endif
除了 H5 平臺,其它平臺均存在的程式碼
#ifdef  H5 ||  MP-WEIXIN
需條件編譯的程式碼
#endif
在 H5 平臺或微信小程式平臺存在的程式碼(這裡只有||,不可能出現&&,因為沒有交集)

%PLATFORM% 可取值如下:

平臺
APP-PLUS App
APP-PLUS-NVUE App nvue
H5 H5
MP-WEIXIN 微信小程式
MP-ALIPAY 支付寶小程式
MP-BAIDU 百度小程式
MP-TOUTIAO 位元組跳動小程式
MP-QQ QQ小程式
MP 微信小程式/支付寶小程式/百度小程式/位元組跳動小程式/QQ小程式

支援的檔案

  • .vue
  • .js
  • .css
  • pages.json
  • 各預編譯語言檔案,如:.scss、.less、.stylus、.ts、.pug

注意: 條件編譯是利用註釋實現的,在不同語法裡註釋寫法不一樣,js使用 // 註釋、css 使用 /* 註釋 */、vue/nvue 模板裡使用 <!-- 註釋 -->;

API 的條件編譯

// #ifdef  %PLATFORM%
平臺特有的API實現
// #endif

示例,如下程式碼僅在 App 下出現:

//#ifdef APP_PLUS
plus.push.addEventListener('click',function(msg){
    var payload = null;
    var action = '';
    if(msg.payload){
        if(typeof msg.payload === 'string'){
            payload = JSON.parse(msg.payload);
        }
        action = payload.action;
        if(action === 'open'){
            plus.webview.open(payload.url)
        }
    }
})
//#endif

示例,如下程式碼不會在 H5 平臺上出現:

//#ifndef H5
uni.scanCode({
    success:(res)=>{
        console.log(res.result);
    }
});
//#endif

除了支援單個平臺的條件編譯外,還支援多平臺同時編譯,使用 || 來分隔平臺名稱。

示例,如下程式碼會在 App 和 H5 平臺上出現:

//#ifdef APP-PLUS || H5
uni.chooseVideo({
    success:(res)=>{
        console.log(res.result);
    }
});
//#endif

元件的條件編譯

<!--  #ifdef  %PLATFORM% -->
平臺特有的元件
<!--  #endif -->

示例,如下廣告元件僅會在微信小程式中出現:

<!-- #ifdef MP-WEIXIN -->
<ad unit-id="test"></ad>
<!-- #endif -->

樣式的條件編譯

/*  #ifdef  %PLATFORM%  */
平臺特有樣式
/*  #endif  */

注意: 樣式的條件編譯,無論是 css 還是 sass/scss/less/stylus 等預編譯語言中,必須使用 /*註釋*/ 的寫法。

正確寫法

/* #ifdef MP-WEIXIN */
.wx-color{
    color:#fff000;
}
/* #endif */

錯誤寫法

// #ifdef MP-WEIXIN
.wx-color{
    color:#fff000
}
// #endif

pages.json 的條件編譯

下面的頁面,只有執行至 App 時才會編譯進去。

// #ifdef APP-PLUS
{
    "path":"pages/api/speech/speech",
    "style":{
        "navigationBarTitleText":"語音識別"
    }
}
//#endif

不同平臺下的特有功能,以及小程式平臺的分包,都可以透過 pages.json 的條件編譯來更好地實現。這樣,就不會在其它平臺產生多餘的資源,進而減小包體積。

json的條件編譯,如不同平臺的key名稱相同,cli專案下開發者自己安裝的校驗器會報錯,需自行關閉這些校驗器對json相同key的校驗規則。如果使用HBuilderX的校驗器,無需在意此問題,HBuilderX的語法校驗器為此最佳化過。

static 目錄的條件編譯

在不同平臺,引用的靜態資源可能也存在差異,透過 static 的的條件編譯可以解決此問題,static 目錄下新建不同平臺的專有目錄(目錄名稱同 %PLATFORM% 值域,但字母均為小寫),專有目錄下的靜態資源只有在特定平臺才會編譯進去。

如以下目錄結構,a.png 只有在微信小程式平臺才會編譯進去,b.png 在所有平臺都會被編譯。

┌─static                
│  ├─mp-weixin
│  │  └─a.png     
│  └─b.png
├─main.js        
├─App.vue      
├─manifest.json 
└─pages.json

整體目錄條件編譯

如果想把各平臺的頁面檔案更徹底的分開,也可以在uni-app專案根目錄建立platforms目錄,然後在下面進一步建立APP-PLUS、MP-WEIXIN等子目錄,存放不同平臺的檔案。

HBuilderX 支援

HBuilderX 為 uni-app 的條件編譯提供了豐富的支援:

程式碼塊支援

在 HBuilderX 中開發 uni-app 時,透過輸入 ifdef 可快速生成條件編譯的程式碼片段

語法高亮

在 HBuilderX 中對條件編譯的程式碼註釋部分提供了語法高亮,可分辨出寫法是否正確,使得程式碼更加清晰(獨立js檔案需在編輯器右下角切換javascript es6+編輯器,獨立css檔案暫不支援高亮,但不高亮不影響使用)

正確註釋和快速選中

在 HBuilderX 中,ctrl+alt+/ 即可生成正確註釋(js:// 註釋、css:/* 註釋 */、vue/nvue模板: <!-- 註釋 -->)。

點選 ifdef 或 endif 可快速選中條件編譯部分;點選左側的摺疊圖示,可摺疊條件編譯部分程式碼。

注意

  • Android 和 iOS 平臺不支援透過條件編譯來區分,如果需要區分 Android、iOS 平臺,請透過呼叫 uni.getSystemInfo 來獲取平臺資訊。支援ifios、ifAndroid程式碼塊,可方便編寫判斷。
  • 有些跨端工具可以提供js的條件編譯或多型,但這對於實際開發遠遠不夠。uni-app不止是處理js,任何程式碼都可以多端條件編譯,才能真正解決實際專案的跨端問題。另外所謂多型在實際開發中會造成大量冗餘程式碼,很不利於複用和維護。舉例,微信小程式主題色是綠色,而百度支付寶小程式是藍色,你的應用想分平臺適配顏色,只有條件編譯是程式碼量最低、最容易維護的。
  • 有些公司的產品運營總是給不同平臺提不同需求,但這不是拒絕uni-app的理由。關鍵在於專案裡,複用的程式碼多還是個性的程式碼多,正常都是複用的程式碼多,所以仍然應該多端。而個性的程式碼放到不同平臺的目錄下,差異化維護。



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70018483/viewspace-2900875/,如需轉載,請註明出處,否則將追究法律責任。

相關文章