uniapp入門(mén)-移動(dòng)端的前端之路

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

uniapp調(diào)研資料

1.認(rèn)識(shí)vue

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

3.組件與api

4.生命周期

5.條件編譯

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

7.小程序打開(kāi)集成原生App插件

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

9.熱更新

10.優(yōu)缺點(diǎn)

demo運(yùn)行指南

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

開(kāi)發(fā)工具下載

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

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

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

然后導(dǎo)入項(xiàng)目并運(yùn)行

項(xiàng)目git地址https://github.com/willShuhuan/DSH_Uni.git

image

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

uniapp是什么

uni-app 是一個(gè)使用 Vue.js 開(kāi)發(fā)所有前端應(yīng)用的框架罪针,開(kāi)發(fā)者編寫(xiě)一套代碼,可發(fā)布到iOS黄伊、Android泪酱、H5、以及各種小程序(微信/支付寶/百度/頭條/QQ/釘釘/淘寶)还最、快應(yīng)用等多個(gè)平臺(tái)墓阀。

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

image

uniapp能力

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

Vue.js優(yōu)點(diǎn)

  1. 體積小
    壓縮后33K乌庶;
  2. 更高的運(yùn)行效率
    基于虛擬dom种蝶,一種可以預(yù)先通過(guò)JavaScript進(jìn)行各種計(jì)算,把最終的DOM操作計(jì)算出來(lái)并優(yōu)化的技術(shù)瞒大,由于這個(gè)DOM操作屬于預(yù)處理操作螃征,并沒(méi)有真實(shí)的操作DOM,所以叫做虛擬DOM透敌。
  3. 雙向數(shù)據(jù)綁定
    讓開(kāi)發(fā)者不用再去操作dom對(duì)象盯滚,把更多的精力投入到業(yè)務(wù)邏輯上;
  4. 生態(tài)豐富酗电、學(xué)習(xí)成本低
    市場(chǎng)上擁有大量成熟魄藕、穩(wěn)定的基于vue.js的ui框架、常用組件撵术!拿來(lái)即用實(shí)現(xiàn)快速開(kāi)發(fā)背率!
    對(duì)初學(xué)者友好、入門(mén)容易嫩与、學(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實(shí)例</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方式 -->
        <!-- 開(kāi)發(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-通過(guò)vue-cli命令行

  1. 安裝npm
    npm全稱(chēng)為Node Package Manager, 是一個(gè)基于Node . js的包管理器处坪,也是整個(gè)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 —> 瀏覽器可視化頁(yè)面 —> 搭建vue 應(yīng)用 -> 使用HBuilder X打開(kāi)

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

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

創(chuàng)建

  • HBuilderX->文件->新建項(xiàng)目->選擇模板
    image

運(yùn)行

https://uniapp.dcloud.io/quickstart?id=運(yùn)行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為開(kāi)發(fā)者提供了一系列基礎(chǔ)組件同窘,類(lèi)似HTML里的基礎(chǔ)標(biāo)簽元素玄帕。
但uni-app的組件與HTML不同,而是與小程序相同想邦,更適合手機(jī)端使用桨仿。

  • 視圖容器:view scroll-view等
  • 基礎(chǔ)內(nèi)容:text icon等
  • 表單組件:button form radio checkbox等
  • 媒體組件:video 等
  • 其他:地圖,導(dǎo)航案狠,畫(huà)布服傍,擴(kuò)展組件等
<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)到新頁(yè)面</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>選項(xiàng)一</text>
                    </label>
                    <label>
                        <radio value="radio2" /><text>選項(xiàng)二</text>
                    </label>
                </radio-group>
                <view class="title">checkbox復(fù)選框</view>
                <checkbox-group name="checkbox">
                    <label>
                        <checkbox value="checkbox1" /><text>選項(xiàng)一</text>
                    </label>
                    <label>
                        <checkbox value="checkbox2" /><text>選項(xiàng)二</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="這是一個(gè)輸入框" />
                <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)準(zhǔn)ECMAScript的js API 和 uni 擴(kuò)展 API 這兩部分組成钱雷。
以上述代碼為例,處理表單提交時(shí)吹零,可以使用uni.showModal彈出一個(gè)提示框

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
    });
}

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

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

image

3.3 自定義組件

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

  • 首先編寫(xiě)一個(gè)組件
<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是自定義組件的一個(gè)屬性-->
        <testComponent style="margin-top: 50px;" msg="默認(rèn)屬性"  @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 整個(gè)應(yīng)用的生命周期

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

  • onLaunch 當(dāng)uni-app 初始化完成時(shí)觸發(fā)(全局只觸發(fā)一次)
  • onShow 當(dāng) uni-app 啟動(dòng)婴洼,或從后臺(tái)進(jìn)入前臺(tái)顯示
  • onHide 當(dāng) uni-app 從前臺(tái)進(jìn)入后臺(tái)
  • onError 當(dāng) uni-app 報(bào)錯(cuò)時(shí)觸發(fā)
  • onUniNViewMessage 對(duì) nvue 頁(yè)面發(fā)送的數(shù)據(jù)進(jìn)行監(jiān)聽(tīng)

下面的代碼中骨坑,在App啟動(dòng)時(shí),為應(yīng)用底部tabBar設(shè)置了消息氣泡柬采,在實(shí)際的開(kāi)發(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 每個(gè)頁(yè)面的生命周期

onLoad粉捻、onShow礁遣、onReady、onHide等

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

4.3 通過(guò)頁(yè)面生命周期控制原生插件的生命周期

在需要與原生插件進(jìn)行交互時(shí),下面的代碼可以通過(guò)監(jiān)聽(tīng)頁(yè)面生命周期控制安卓原生插件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 簡(jiǎn)介

語(yǔ)法: 以 #ifdef 或 #ifndef 加 %PLATFORM% 開(kāi)頭盈包,以 #endif 結(jié)尾沸呐。

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

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

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

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

<template>
    <!--  #ifdef  %PLATFORM% -->
    平臺(tái)特有的組件
    <!--  #endif -->
</template>

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

<style>
    /*  #ifdef  %PLATFORM%  */
    平臺(tái)特有樣式
    /*  #endif  */
</style>

5.2 pages.json條件編譯

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

{
    "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中的條件編譯代碼要一致,否則運(yùn)行時(shí)會(huì)報(bào)錯(cuò)</p>

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

image

效果
其他平臺(tái)
image

微信平臺(tái)
image

5.3 API條件編譯

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

查看以下代碼

  • v-show 屬性可以理解為css的display屬性力试,控制組件顯示隱藏
  • 通過(guò)帶參函數(shù)show(param)返回值控制v-show的值
  • gotoNativePage()是一個(gè)跳轉(zhuǎn)到原生App頁(yè)面的一個(gè)方法,需要原生插件的支持
  • ifios和ifAndroid可以針對(duì)移動(dòng)端平臺(tái)進(jìn)行處理
<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>

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

  • 在H5平臺(tái)下 安卓和 ios跳轉(zhuǎn)按鈕都展示
  • 在安卓平臺(tái)下排嫌,只會(huì)展示跳轉(zhuǎn)安卓activity按鈕
  • 在iOS平臺(tái)下畸裳,只會(huì)展示跳轉(zhuǎn)iOS viewController的按鈕
image

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

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

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

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

image

流程

  • 原生工程中 添加基礎(chǔ)依賴(lài)庫(kù)及資源文件
 uniMPSDK-release.aar  //必須集成
 uniapp-release.aar //必須集成
 sqlite-release.aar
 msa_mdid_1.0.13.aar //必須集成 注意(2.8.0版本的SDK及以下版本請(qǐng)集成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è)置值域超過(guò)28可能在android10以上手機(jī)出現(xiàn)白屏問(wèn)題帅容。
        ndk {
            abiFilters 'x86','armeabi-v7a',"arm64-v8a" //不支持armeabi
        }
        manifestPlaceholders = mfph
    }
    //此處配置必須添加 否則無(wú)法正確運(yùn)行
    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)依賴(lài)jar、aar
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation fileTree(include: ['*.aar'], dir: 'libs')
    //必須添加的依賴(lài)
    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)用資源
    打開(kāi)android原生項(xiàng)目并徘。在主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

注意,以下配置項(xiàng)必須添加劝评,并且按照要求填寫(xiě)姐直,否則不停報(bào)錯(cuò)

image

在原生App中開(kāi)啟小程序

    //配置菜單
    MenuActionSheetItem item = new MenuActionSheetItem("關(guān)于", "gy");
    MenuActionSheetItem item1 = new MenuActionSheetItem("獲取當(dāng)前頁(yè)面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)//開(kāi)啟后臺(tái)運(yùn)行
            .build();
    //開(kāi)啟小程序            
    DCUniMPSDK.getInstance().startApp(mContext,"__UNI__1F21932","/pages/product/product?id=10");
        

<h2 id="chapacter7">7.小程序集成原生App插件</h2>
uniapp支持原生插件擴(kuò)展,包括插件市場(chǎng)云端插件和本地插件兩種方式蒋畜,這節(jié)講解云端插件声畏,本地插件在第8節(jié)進(jìn)行說(shuō)明

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

    image

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


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

    image

  • 自定義基座

    image

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

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

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

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

擴(kuò)展 module

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

image

  • 1.首先創(chuàng)建一個(gè)AS工程辫狼,工程內(nèi)創(chuàng)建Android Library,導(dǎo)入uniapp-relase.aar并依賴(lài)
  • 2.編寫(xiě)Module類(lèi)辛润,設(shè)計(jì)交互場(chǎng)景
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 編寫(xiě)通過(guò)Module進(jìn)行交互的業(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 通過(guò)gradle執(zhí)行打包構(gòu)建aar文件
image
image
  • 5 配置package.json


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

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

    image

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

    image

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


    image
  • 10 在真機(jī)或模擬器上運(yùn)行,點(diǎn)擊加載fragment按鈕乎澄,效果如下


    image

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

小程序平臺(tái)升級(jí)

uni-app發(fā)布為小程序的升級(jí)模式較簡(jiǎn)單突硝,只需將開(kāi)發(fā)完的代碼提交小程序后臺(tái),待審核通過(guò)后用戶(hù)將自動(dòng)升級(jí)置济。

APP端的升級(jí)

App資源熱更新

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

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

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

雖然下面寫(xiě)了更多的缺點(diǎn)痒谴,但總體來(lái)看衰伯,優(yōu)點(diǎn)遠(yuǎn)大于缺點(diǎn)

優(yōu)點(diǎn)

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

缺點(diǎn)

  • 正是由于跨平臺(tái)特性槐雾,多端適配會(huì)占據(jù)相當(dāng)?shù)墓ぷ髁浚_(kāi)發(fā)人員必須編寫(xiě)很多條件編譯代碼幅狮,這會(huì)破壞代碼的整體結(jié)構(gòu)(畢竟在業(yè)務(wù)代碼中編寫(xiě)很多平臺(tái)適配代碼看起來(lái)太不優(yōu)雅了)募强,可讀性也會(huì)受到一定影響,而且坑多是必然的
  • 對(duì)于Android和iOS開(kāi)發(fā)人員來(lái)講崇摄,轉(zhuǎn)投uniapp學(xué)習(xí)成本很高(除了vue擎值,還要學(xué)習(xí)html+js+css等知識(shí)),精通更是很難逐抑,這有點(diǎn)類(lèi)似前兩年移動(dòng)端轉(zhuǎn)投react native那樣鸠儿,會(huì)而不精,代碼質(zhì)量無(wú)法得到充分保證(我也有朋友最近把公司的react native的項(xiàng)目完全重構(gòu)為原生代碼了)
  • 前端人員依然無(wú)法解決所有問(wèn)題厕氨,至少在目前的應(yīng)用場(chǎng)景中进每,很多需求仍然需要客戶(hù)端人員配合開(kāi)發(fā)(對(duì)于前端人員而言,學(xué)習(xí)安卓iOS的成本也相當(dāng)可觀)
  • 對(duì)于一些棘手的問(wèn)題腐巢,參考的資料并不多品追,而且官方也很難第一時(shí)間回答你玄括,甚至只能自己慢慢探索
  • 陳舊的api:以安卓為例冯丙,uniapp云打包apk反編譯之后,發(fā)現(xiàn)入口程序PandoraEntry實(shí)際上是一個(gè)Activity而非API22(Android 5.1)后谷歌官方建議使用的v7包下的AppCompactActivity,這會(huì)影響ToolBar的使用
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胃惜,一起剝皮案震驚了整個(gè)濱河市泞莉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌船殉,老刑警劉巖鲫趁,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異利虫,居然都是意外死亡挨厚,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)糠惫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疫剃,“玉大人,你說(shuō)我怎么就攤上這事硼讽〕布郏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵固阁,是天一觀的道長(zhǎng)壤躲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)备燃,這世上最難降的妖魔是什么碉克? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮赚爵,結(jié)果婚禮上棉胀,老公的妹妹穿的比我還像新娘。我一直安慰自己冀膝,他們只是感情好唁奢,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著窝剖,像睡著了一般麻掸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赐纱,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天脊奋,我揣著相機(jī)與錄音,去河邊找鬼疙描。 笑死诚隙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的起胰。 我是一名探鬼主播久又,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了地消?” 一聲冷哼從身側(cè)響起炉峰,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脉执,沒(méi)想到半個(gè)月后疼阔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡半夷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年婆廊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巫橄。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡否彩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗦随,到底是詐尸還是另有隱情列荔,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布枚尼,位于F島的核電站贴浙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏署恍。R本人自食惡果不足惜崎溃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盯质。 院中可真熱鬧袁串,春花似錦、人聲如沸呼巷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)王悍。三九已至破镰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間压储,已是汗流浹背鲜漩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留集惋,地道東北人孕似。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像刮刑,于是被迫代替她去往敵國(guó)和親喉祭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霸饲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345