uniapp入門-移動端的前端之路

學(xué)習(xí)導(dǎo)覽

uniapp調(diào)研資料

1.認識vue

2.搭建vue應(yīng)用

3.組件與api

4.生命周期

5.條件編譯

6.原生APP中集成uni小程序

7.小程序打開集成原生App插件

8.原生插件開發(fā)

9.熱更新

10.優(yōu)缺點

demo運行指南

首先安裝HBuilderX和微信開發(fā)者程序

開發(fā)工具下載

https://www.dcloud.io/hbuilderx.html

微信開發(fā)者工具下載(小程序預(yù)覽需要)

https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

然后導(dǎo)入項目并運行

項目git地址https://github.com/willShuhuan/DSH_Uni.git

image

<h2 id="chapacter1">1.認識vue</h2>
Vue (讀音 /vju?/,類似于 view) 是一套用于構(gòu)建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設(shè)計為可以自底向上逐層應(yīng)用。Vue 的核心庫只關(guān)注視圖層,不僅易于上手,還便于與第三方庫或既有項目整合。另一方面,當(dāng)與現(xiàn)代化的工具鏈以及各種支持類庫結(jié)合使用時,Vue 也完全能夠為復(fù)雜的單頁應(yīng)用提供驅(qū)動。

uniapp是什么

uni-app 是一個使用 Vue.js 開發(fā)所有前端應(yīng)用的框架,開發(fā)者編寫一套代碼,可發(fā)布到iOS、Android、H5、以及各種小程序(微信/支付寶/百度/頭條/QQ/釘釘/淘寶)、快應(yīng)用等多個平臺。

多端運行的原因->目標(biāo)平臺安裝文件打包

image

uniapp能力

能力 Y/N 說明
跨端能力 ? 安卓、ios、微信小程序、其他小程序
原生App喚起uni小程序能力 ? 需要集成uni小程序SDK并導(dǎo)入小程序wgt包
原生App跳轉(zhuǎn)小程序二級頁面 ? 可以傳遞json、字符串等
uni小程序喚起原生App能力 ? 需要開發(fā)對應(yīng)的Android/iOS插件,或通過插件市場下載,支持json、字符串等通用數(shù)據(jù)類型的傳遞
第三方服務(wù) ? 支付/推送/三方登錄/分享/地圖等
HBuilderX熱編譯 ? 支持手機、微信、瀏覽器實時預(yù)覽
fragment/viewController嵌套小程序頁面 ? 啟動小程序相當(dāng)于打開一個新的Activity,詳見頁面最下說明
uniapp頁面加載原生fragment/viewController ? uni小程序在App端實際上是運行在一個WebActivity之上,可以拿到ActivityContext進而獲取FragmentManager處理Fragment的展示隱藏,雖然這種方式可行,但是在uniapp上切換選項卡的時候要不斷處理fragment的內(nèi)部邏輯,相當(dāng)于fragment生命周期的監(jiān)控任務(wù)交給uniapp來執(zhí)行而不是fragment本身

Vue.js優(yōu)點

  1. 體積小
    壓縮后33K;
  2. 更高的運行效率
    基于虛擬dom,一種可以預(yù)先通過JavaScript進行各種計算,把最終的DOM操作計算出來并優(yōu)化的技術(shù),由于這個DOM操作屬于預(yù)處理操作,并沒有真實的操作DOM,所以叫做虛擬DOM。
  3. 雙向數(shù)據(jù)綁定
    讓開發(fā)者不用再去操作dom對象,把更多的精力投入到業(yè)務(wù)邏輯上;
  4. 生態(tài)豐富、學(xué)習(xí)成本低
    市場上擁有大量成熟、穩(wěn)定的基于vue.js的ui框架、常用組件!拿來即用實現(xiàn)快速開發(fā)!
    對初學(xué)者友好、入門容易、學(xué)習(xí)資料多;

<h2 id="chapacter2">2.搭建vue應(yīng)用</h2>

2.1 html內(nèi)嵌式

使用cdn或者本地文件的形式引入vue(不建議使用,知道就好)

<html>
    <head>
        <meta charset="utf-8">
        <title>vue實例</title>
        <!-- 直接引入方式 -->
        <!-- <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script> -->
        <!-- <script src="../js/vue.min.js" type="text/javascript" charset="utf-8"></script> -->
        
        <!-- cdn方式 -->
        <!-- 開發(fā)環(huán)境版本,包含了有幫助的命令行警告 -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <!-- 生產(chǎn)環(huán)境版本,優(yōu)化了尺寸和速度 -->
        <!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> -->
    </head>
    <body>
    </body>
<html>

2.2 vue cli 終端命令行安裝(需要掌握)

https://uniapp.dcloud.io/quickstart?id=_2-通過vue-cli命令行

  1. 安裝npm
    npm全稱為Node Package Manager, 是一個基于Node . js的包管理器,也是整個Node . js社區(qū)最流行、支持的第三方模塊最多的包管理器。
    npm -v 查看npm
  2. 安裝cnpm
    npm install -g cnpm -registry=https://registry.npm. taobao.org
  3. 安裝vue一cli
    cnpm install -g @vue/cli
  4. 安裝webpack
    cnpm install -g webpack
    webpack是JavaScript 打包器(module bundler)
  5. vue ui —> 瀏覽器可視化頁面 —> 搭建vue 應(yīng)用 -> 使用HBuilder X打開

2.3 HBuilder X 搭建uniapp(建議使用)

https://uniapp.dcloud.io/quickstart?id=_1-通過-hbuilderx-可視化界面

創(chuàng)建

  • HBuilderX->文件->新建項目->選擇模板
    image

運行

https://uniapp.dcloud.io/quickstart?id=運行uni-app

image

image

image

發(fā)布

image

<h2 id="chapacter3">3.組件與api</h2>
https://uniapp.dcloud.io/component/README
https://uniapp.dcloud.io/api/README

3.1 組件的使用

uni-app為開發(fā)者提供了一系列基礎(chǔ)組件,類似HTML里的基礎(chǔ)標(biāo)簽元素。
但uni-app的組件與HTML不同,而是與小程序相同,更適合手機端使用。

  • 視圖容器:view scroll-view等
  • 基礎(chǔ)內(nèi)容:text icon等
  • 表單組件:button form radio checkbox等
  • 媒體組件:video 等
  • 其他:地圖,導(dǎo)航,畫布,擴展組件等
<template>
    <view class="content">
        <scroll-view show-scrollbar="false">

            <navigator style="width: 100%; margin-top: 10rpx;" url="./tab_main_task" hover-class="navigator-hover" open-type="switchTab">
                <button type="primary">navigator跳轉(zhuǎn)到新頁面</button>
            </navigator>

            <video style="width: 100%; margin-top: 10rpx;" src="http://gusteau-test.oss-cn-hangzhou.aliyuncs.com/material/transcode/video/2020/07/24/HK2mmdYW_1595570205480.mp4"></video>

            <form @submit="formSubmit" @reset="formReset" class="form">
                <view class="title">{{switchvalue}}</view>
                <switch @change="switchChange" color="#FF6723" name="switch"></switch>
                <view class="title">radio單選框</view>
                <radio-group name="radio">
                    <label>
                        <radio value="radio1" /><text>選項一</text>
                    </label>
                    <label>
                        <radio value="radio2" /><text>選項二</text>
                    </label>
                </radio-group>
                <view class="title">checkbox復(fù)選框</view>
                <checkbox-group name="checkbox">
                    <label>
                        <checkbox value="checkbox1" /><text>選項一</text>
                    </label>
                    <label>
                        <checkbox value="checkbox2" /><text>選項二</text>
                    </label>
                </checkbox-group>
                <view class="title">slider</view>
                <slider value="50" name="slider" show-value></slider>
                <view class="title">input輸入框</view>
                <input class="uni-input" name="input" placeholder="這是一個輸入框" />
                <button form-type="submit" type="primary" class="button">Submit</button>
                <button type="warn" form-type="reset" class="button">Reset</button>
            </form>


        </scroll-view>

    </view>
</template>

3.2 API調(diào)用

uni-app的js API由標(biāo)準ECMAScript的js API 和 uni 擴展 API 這兩部分組成。
以上述代碼為例,處理表單提交時,可以使用uni.showModal彈出一個提示框

formSubmit: function(e) {
    console.log('form發(fā)生了submit事件,攜帶數(shù)據(jù)為:' + JSON.stringify(e.detail.value))
    var formdata = e.detail.value
    uni.showModal({
        content: '表單數(shù)據(jù)內(nèi)容:' + JSON.stringify(formdata),
        showCancel: false
    });
}

如果想模擬一個網(wǎng)絡(luò)請求,可以這樣

uni.request({
    url: 'https://www.example.com/request', //僅為示例,并非真實接口地址。
    data: {
        text: 'uni.request'
    },
    header: {
        'custom-header': 'hello' //自定義請求頭信息
    },
    success: (res) => {
        console.log(res.data);
        this.text = 'request success';
    }
});
image

image

3.3 自定義組件

封裝可復(fù)用的組件,可以在其他的頁面使用它

  • 首先編寫一個組件
<template>
    <h3 @click='clickFun'>我是自定義組件:{{msg}}</h3>
</template>

<script>
    export default {
        name:'testComponent',
        props:{
            msg:{
                type:String,
                default:'default msg'
            }
        },
        methods:{
            clickFun:function(){
                this.msg = '改變后的組件屬性',
                this.$emit('clickFun',this.msg);
            }
        }
    }
</script>
<style>
</style>

  • 在其他的組件中導(dǎo)入、聲明、傳入必要的參數(shù)并使用它
<template>
    <view>
        <!-- 3.自定義組件使用 msg是自定義組件的一個屬性-->
        <testComponent style="margin-top: 50px;" msg="默認屬性"  @clickFun="sonComponentClickCallback"></testComponent>
        <div>{{callback}}</div>
    </view>
</template>
<script>
    //1.導(dǎo)入
    import testComponent from '../components/testcomponent.vue'
    
    export default{
        components:{
            //2.聲明
            testComponent
        },
        data() {
            return {
                callback: ''
            }
        },
        methods:{
            sonComponentClickCallback:function(e){
                // this.callback = e;
                console.log(e);
            }
        }
    }
</script>

<style>

</style>
image

<h2 id="chapacter4">4.生命周期</h2>
https://uniapp.dcloud.io/collocation/frame/lifecycle

4.1 整個應(yīng)用的生命周期

只能在App.vue中監(jiān)聽,

  • onLaunch 當(dāng)uni-app 初始化完成時觸發(fā)(全局只觸發(fā)一次)
  • onShow 當(dāng) uni-app 啟動,或從后臺進入前臺顯示
  • onHide 當(dāng) uni-app 從前臺進入后臺
  • onError 當(dāng) uni-app 報錯時觸發(fā)
  • onUniNViewMessage 對 nvue 頁面發(fā)送的數(shù)據(jù)進行監(jiān)聽

下面的代碼中,在App啟動時,為應(yīng)用底部tabBar設(shè)置了消息氣泡,在實際的開發(fā)中,也可以做一些資源和SDK的初始化工作,比如為安卓和iOS原生插件內(nèi)部的SDK做一些初始化工作

<script>
    export default {
        onLaunch: function() {
            console.log('App Launch')
            setTimeout(() => {
                uni.setTabBarBadge({
                    index: 1,
                    text: '9'
                });
                uni.showTabBarRedDot({
                    index: 3
                });
            }, 1000);
        },
        onShow: function() {
            console.log('App Show')
        },
        onHide: function() {
            console.log('App Hide')
        },
    }
</script>

4.2 每個頁面的生命周期

onLoad、onShow、onReady、onHide等

  • onPageScroll 頁面在垂直方向已滾動的距離(單位px)
    onPageScroll:function(e){
        this.scrollTop = e.scrollTop;
    }
  • onBackPress 觸發(fā)返回行為的來源:'backbutton'——左上角導(dǎo)航欄按鈕及安卓返回鍵;'navigateBack'——uni.navigateBack() 方法。
  • onTabItemTap 當(dāng)前點擊的tabItem
    • 返回對象 {"index":4,"text":"我的","pagePath":"pages/main/tab_main_mine"}
      image

4.3 通過頁面生命周期控制原生插件的生命周期

在需要與原生插件進行交互時,下面的代碼可以通過監(jiān)聽頁面生命周期控制安卓原生插件fragment的顯示隱藏

onHide() {
    console.log("onHide");
    testModule.hideFragment();
},
onShow() {
    console.log("onShow");
    testModule.showFragment();
}

<h2 id="chapacter5">5.條件編譯</h2>
【官網(wǎng)介紹】 https://uniapp.dcloud.io/platform

5.1 簡介

語法: 以 #ifdef 或 #ifndef 加 %PLATFORM% 開頭,以 #endif 結(jié)尾。

  • ifdef:if defined 僅在某平臺存在
  • ifndef:if not defined 除了某平臺均存在
  • %PLATFORM%:平臺名稱
#ifdef APP-PLUS
需條件編譯的代碼
#endif

#ifndef H5
需條件編譯的代碼
#endif

#ifdef H5 || MP-WEIXIN
需條件編譯的代碼
#endif

在vue中的使用,與注釋代碼的語法一致,mac下command+/或者control+alt+/提示

<template>
    <!--  #ifdef  %PLATFORM% -->
    平臺特有的組件
    <!--  #endif -->
</template>

<script>
    // #ifdef APP-PLUS
    平臺特有API實現(xiàn)
    // #endif
</script>

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

5.2 pages.json條件編譯

例:實現(xiàn)微信小程序和客戶端的差異化顯示
pages.json中使用條件編譯注釋微信平臺需要屏蔽的頁面

{
    "pages":[
        //#ifndef MP-WEIXIN
        {
            "path": "pages/main/tab_main_video",
            "style": {}
        },
        {
            "path" : "pages/main/tab_main_game",
            "style" : {}
        },
        //#endif
        ...
    ],
    "tabBar" : {
        ...
        "list":[
            //#ifndef MP-WEIXIN
            {
                "pagePath" : "pages/main/tab_main_video",
                "iconPath" : "static/mipmap/tabbar/ic_nav_video_unselected.png",
                "selectedIconPath" : "static/mipmap/tabbar/ic_nav_video_selected.png",
                "text" : "刷視頻"
            },
            {
                "pagePath" : "pages/main/tab_main_game",
                "iconPath" : "static/mipmap/tabbar/ic_nav_game_unselected.png",
                "selectedIconPath" : "static/mipmap/tabbar/ic_nav_game_selected.png",
                "text" : "玩游戲"
            },
            // #endif
        ]
        
        ...
    }
}

<p style="color:red">注意:pages中條件編譯的代碼要與tabbar中的條件編譯代碼要一致,否則運行時會報錯</p>

編譯之后在微信開發(fā)者工具下看到代碼不包含被我們條件編譯排除掉的代碼,可以說HBuilderX在編譯過程中幫我們?nèi)サ袅似脚_無關(guān)代碼

image

效果
其他平臺
image

微信平臺
image

5.3 API條件編譯

  • 針對各個平臺的特性不同,處理一些交互,比如表單校驗提示,在原生APP可以以吐司形式,在H5平臺上可以處理為Alert彈出框
  • 控制各個平臺業(yè)務(wù)代碼的差異

查看以下代碼

  • v-show 屬性可以理解為css的display屬性,控制組件顯示隱藏
  • 通過帶參函數(shù)show(param)返回值控制v-show的值
  • gotoNativePage()是一個跳轉(zhuǎn)到原生App頁面的一個方法,需要原生插件的支持
  • ifios和ifAndroid可以針對移動端平臺進行處理
<template>
    <div>
        <div class="content">
            <button v-show="show('android')"  class="button" type="primary" @click="gotoNativePage">Android跳轉(zhuǎn)原生Activity</button>
            <button v-show="show('ios')" class="button" type="primary" @click="gotoNativePage">iOS跳轉(zhuǎn)原生ViewController</button>
        </div>
    </div>

</template>
<script>
    const testModule = uni.requireNativePlugin("willA-SopModule");
    export default {
        data() {
            return {
                title: 'Hello',
                show: function(plat){
                    // #ifdef H5
                    return true
                    // #endif
                    // #ifdef APP-PLUS
                    if(plat==='android'){
                        if (uni.getSystemInfoSync().platform == "android") {
                            return true
                        }else{
                            return false
                        }
                    }else{
                        if (uni.getSystemInfoSync().platform == "android") {
                            return false
                        }else{
                            return true
                        }
                    }
                    // #endif
                }
                    
            }
        }
    
    };
</script>


<style>
    .content {
        text-align: center;
        height: 100%;
        margin-top: 150upx;
    }

    .button {
        width: 60%;
        margin-top: 100upx;
    }
</style>

上述代碼運行結(jié)果就是:

  • 在H5平臺下 安卓和 ios跳轉(zhuǎn)按鈕都展示
  • 在安卓平臺下,只會展示跳轉(zhuǎn)安卓activity按鈕
  • 在iOS平臺下,只會展示跳轉(zhuǎn)iOS viewController的按鈕
image

其他條件編譯的使用場景放在第7小節(jié)講解

<h2 id="chapacter6">6.原生APP中集成uni小程序</h2>

https://nativesupport.dcloud.net.cn/UniMPDocs/UseSdk/android

uni小程序SDK,是為原生App打造的可運行基于 uni-app 開發(fā)的小程序前端項目的框架,從而幫助原生App快速獲取小程序的能力,效果如下:

image

流程

  • 原生工程中 添加基礎(chǔ)依賴庫及資源文件
 uniMPSDK-release.aar  //必須集成
 uniapp-release.aar //必須集成
 sqlite-release.aar
 msa_mdid_1.0.13.aar //必須集成 注意(2.8.0版本的SDK及以下版本請集成miit_mdid_1.0.10.aar)
 messaging-release.aar
 iBeacon-release.aar
 fingerprint-release.aar
 contacts-release.aar
 Bluetooth-release.aar
 android-gif-drawable-release@1.2.17.aar //必須集成

gradle配置

//必須配置
def mfph = [
    //宿主包名
    "apk.applicationId" : "xxx.xxx.xxxxx",
]
android {
    defaultConfig {
        targetSdkVersion 26 //最高28最優(yōu)26 設(shè)置值域超過28可能在android10以上手機出現(xiàn)白屏問題。
        ndk {
            abiFilters 'x86','armeabi-v7a',"arm64-v8a" //不支持armeabi
        }
        manifestPlaceholders = mfph
    }
    //此處配置必須添加 否則無法正確運行
    aaptOptions {
        additionalParameters '--auto-add-overlay'
        //noCompress 'foo', 'bar'
        ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"
    }
}
//導(dǎo)入aar需要的配置
repositories {
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    //導(dǎo)入SDK相關(guān)依賴jar、aar
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation fileTree(include: ['*.aar'], dir: 'libs')
    //必須添加的依賴
    implementation 'com.android.support:recyclerview-v7:27.1.0'
    implementation 'com.android.support:support-v4:27.1.0'
    implementation 'com.android.support:appcompat-v7:27.1.0'
    implementation 'com.alibaba:fastjson:1.1.46.android'
    implementation 'com.facebook.fresco:fresco:1.13.0'
    implementation 'com.facebook.fresco:animated-gif:1.13.0'
    implementation 'com.github.bumptech.glide:glide:4.9.0'
}
image
  • 生成小程序應(yīng)用資源, 在uniapp中制作wgt包

    image

  • 導(dǎo)入小程序應(yīng)用資源
    打開android原生項目。在主Module模塊的assets路徑下創(chuàng)建apps/(內(nèi)置uni小程序的appid)/www 路徑。例如:apps/__UNI__04E3A11/www。將之前導(dǎo)出的應(yīng)用資源包解壓釋放到apps/__UNI__04E3A11/www路徑下。

小程序id在uniapp工程中可以看到

image

安卓工程配置

image

注意,以下配置項必須添加,并且按照要求填寫,否則不停報錯

image

在原生App中開啟小程序

    //配置菜單
    MenuActionSheetItem item = new MenuActionSheetItem("關(guān)于", "gy");
    MenuActionSheetItem item1 = new MenuActionSheetItem("獲取當(dāng)前頁面url", "hqdqym");
    List<MenuActionSheetItem> sheetItems = new ArrayList<>();
    sheetItems.add(item);
    sheetItems.add(item1);
    DCSDKInitConfig config = new DCSDKInitConfig.Builder()
            .setCapsule(true)
            .setMenuDefFontSize("16px")
            .setMenuDefFontColor("#ff00ff")
            .setMenuDefFontWeight("normal")
            .setMenuActionSheetItems(sheetItems)
            .setEnableBackground(true)//開啟后臺運行
            .build();
    //開啟小程序            
    DCUniMPSDK.getInstance().startApp(mContext,"__UNI__1F21932","/pages/product/product?id=10");
        

<h2 id="chapacter7">7.小程序集成原生App插件</h2>
uniapp支持原生插件擴展,包括插件市場云端插件和本地插件兩種方式,這節(jié)講解云端插件,本地插件在第8節(jié)進行說明

  • 首先在manifest中選擇云端插件

    image

  • 在插件市場導(dǎo)入


    image
  • 回到HBuilderX中導(dǎo)入插件

    image

  • 自定義基座

    image

  • 打包完成之后,按照插件使用說明在需要的地方引入并使用它,效果如下

<script>
    //在頁面中引入插件
    const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert')
    export default{
        onTabItemTap:function(Object){
            console.log(Object);
        },
        methods:{
            showPlugin(){
                //編寫調(diào)用代碼
                dcRichAlert.doSomthing();
            }
        }
    }
</script>
image

<h2 id="chapacter8">8.原生插件開發(fā)</h2>
當(dāng)HBuilderX中提供的能力無法滿足App功能需求,需要通過使用Andorid/iOS原生開發(fā)實現(xiàn)時,可使用App離線SDK開發(fā)原生插件來擴展原生能力。
https://nativesupport.dcloud.net.cn/NativePlugin/course/android

  • 擴展 module(偏向功能模塊)
  • 擴展組件 component(偏向UI組件)

擴展 module

https://nativesupport.dcloud.net.cn/NativePlugin/course/android?id=創(chuàng)建android-studio的module模塊

image

  • 1.首先創(chuàng)建一個AS工程,工程內(nèi)創(chuàng)建Android Library,導(dǎo)入uniapp-relase.aar并依賴
  • 2.編寫Module類,設(shè)計交互場景
public class TestModule extends WXModule {

    private static final String TAG = "uniTestModule";
    FragmentManager fragmentManager;
    FragmentTransaction transaction;
    Fragment fragment;
    Context mContext;
    FrameLayout frameLayout;

    //run ui thread
    @JSMethod(uiThread = true)
    public void testAsyncFunc(JSONObject options, JSCallback callback) {
        Log.e(TAG, "testAsyncFunc--"+options);
        if(callback != null) {
            JSONObject data = new JSONObject();
            data.put("code", "success");
            callback.invoke(data);
            //callback.invokeAndKeepAlive(data);
        }
    }

    //run JS thread
    @JSMethod (uiThread = false)
    public JSONObject testSyncFunc(){
        JSONObject data = new JSONObject();
        data.put("code", "success");
        return data;
    }

    @JSMethod (uiThread = true)
    public void gotoNativeMainPage(JSONObject jsonObject){
        Log.d(TAG, "gotoNativeMainPage: "+jsonObject);
        if(mWXSDKInstance != null) {
            Intent intent = new Intent(mWXSDKInstance.getContext(), TestActivity.class);
            intent.putExtra("data",jsonObject.toString());
            mWXSDKInstance.getContext().startActivity(intent);
        }
    }

    @JSMethod (uiThread = true)
    public void showFragment(){
        mContext = mWXSDKInstance.getContext();
        Log.d(TAG, "showFragment: "+mContext);//PandoraEntryActivity
        fragmentManager = ((Activity) mContext).getFragmentManager();
        transaction = fragmentManager.beginTransaction();  
        fragment = new TestFragment();
        frameLayout = new FrameLayout(mContext);

        int height = Util.getScreenHeidth(mContext);
        int bottomMargin =  Util.dip2px(mContext,50);

        FrameLayout.LayoutParams params1 =new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                height-bottomMargin
        );
        ((Activity) mContext).addContentView(frameLayout,params1);
        frameLayout.setId(View.generateViewId());
        transaction.replace(frameLayout.getId(), fragment);
        transaction.commitAllowingStateLoss();
    }


    @JSMethod (uiThread = true)
    public void hideFragment(){
        transaction = fragmentManager.beginTransaction();
        transaction.hide(fragment).commit();
        fragment.onPause();
    }


}
  • 3 編寫通過Module進行交互的業(yè)務(wù)代碼
public class TestFragment extends Fragment {

    private static final String TAG = "uniTestModule";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.mine_layout, container,false);
        return view;
    }
}

public class TestActivity extends AppCompatActivity {
    private static final String TAG = "uniTestModule";

    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String  data = getIntent().getStringExtra("data");
        setContentView(R.layout.activity_test);
        TextView textView = findViewById(R.id.text);
        textView.setText(data);

    }
}

  • 4 通過gradle執(zhí)行打包構(gòu)建aar文件
image
image
  • 5 配置package.json


    image
  • 6 將插件集成到項目中
    項目根目錄下新建nativeplugins文件夾,將package.json放入此目錄,新建android文件夾放入安卓打包aar文件,新建ios文件夾配置放置ios打包.a文件

  • 7 manifest文件中配置本地模塊

    image

  • 8 制作自定義基座(云打包)

    image

  • 9 等待打包完成,在需要使用的地方調(diào)用插件即可


    image
  • 10 在真機或模擬器上運行,點擊加載fragment按鈕,效果如下


    image

<h2 id="chapacter9">9.熱更新</h2>

小程序平臺升級

uni-app發(fā)布為小程序的升級模式較簡單,只需將開發(fā)完的代碼提交小程序后臺,待審核通過后用戶將自動升級。

APP端的升級

App資源熱更新

https://ask.dcloud.net.cn/article/id-35667__page-4
適用小版本升級
通過生成移動APP資源升級包的方式進行差量(增量)升級,將uniapp發(fā)布為wgt升級包,通過服務(wù)端與前端配合的方式在移動端進行升級

  • 以安卓為例,uniapp打包apk的過程就是把當(dāng)前uniapp工程包裝為一個安卓工程并進行壓縮打包的過程,uniapp中的代碼運行在一個Webview中(原生插件除外)
  • 實際上,所以我們修改uniapp的代碼也只是修改了前端代碼,不管打包前還是打包為apk之后,也不可能中間會存在js2java或者js2OC這樣的代碼轉(zhuǎn)換過程(如果真有這種黑科技,就能真正的一統(tǒng)天下了)
  • 所以,只需要把wgt升級包放在服務(wù)端,App端檢測到版本升級時,下載wgt資源并替換原來的資源就可以了,實際上,Tinker(http://www.itdecent.cn/p/076afb5cdd55) 等熱更新方案也是類似的原理
    image

<h2 id="chapacter10">10.優(yōu)缺點</h2>
<strong style="color:red;font-size:20px">結(jié)論:優(yōu)點>缺點</strong>

雖然下面寫了更多的缺點,但總體來看,優(yōu)點遠大于缺點

優(yōu)點

  • 跨平臺性,write once ,run everywhere,通過多平臺打包發(fā)布到對應(yīng)平臺,節(jié)約大量開發(fā)成本
  • 對于前端開發(fā)人員比較友好,vue作為主流前端框架大多數(shù)人都掌握,只需要少量原生知識就能夠開發(fā)跨平臺的應(yīng)用
  • 生態(tài)體系逐漸完善,很多大廠也在用,社區(qū)成長速度比較快

缺點

  • 正是由于跨平臺特性,多端適配會占據(jù)相當(dāng)?shù)墓ぷ髁?,開發(fā)人員必須編寫很多條件編譯代碼,這會破壞代碼的整體結(jié)構(gòu)(畢竟在業(yè)務(wù)代碼中編寫很多平臺適配代碼看起來太不優(yōu)雅了),可讀性也會受到一定影響,而且坑多是必然的
  • 對于Android和iOS開發(fā)人員來講,轉(zhuǎn)投uniapp學(xué)習(xí)成本很高(除了vue,還要學(xué)習(xí)html+js+css等知識),精通更是很難,這有點類似前兩年移動端轉(zhuǎn)投react native那樣,會而不精,代碼質(zhì)量無法得到充分保證(我也有朋友最近把公司的react native的項目完全重構(gòu)為原生代碼了)
  • 前端人員依然無法解決所有問題,至少在目前的應(yīng)用場景中,很多需求仍然需要客戶端人員配合開發(fā)(對于前端人員而言,學(xué)習(xí)安卓iOS的成本也相當(dāng)可觀)
  • 對于一些棘手的問題,參考的資料并不多,而且官方也很難第一時間回答你,甚至只能自己慢慢探索
  • 陳舊的api:以安卓為例,uniapp云打包apk反編譯之后,發(fā)現(xiàn)入口程序PandoraEntry實際上是一個Activity而非API22(Android 5.1)后谷歌官方建議使用的v7包下的AppCompactActivity,這會影響ToolBar的使用
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容