學(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
<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)安裝文件打包
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)
- 體積小
壓縮后33K乌庶; - 更高的運(yùn)行效率
基于虛擬dom种蝶,一種可以預(yù)先通過(guò)JavaScript進(jìn)行各種計(jì)算,把最終的DOM操作計(jì)算出來(lái)并優(yōu)化的技術(shù)瞒大,由于這個(gè)DOM操作屬于預(yù)處理操作螃征,并沒(méi)有真實(shí)的操作DOM,所以叫做虛擬DOM透敌。 - 雙向數(shù)據(jù)綁定
讓開(kāi)發(fā)者不用再去操作dom對(duì)象盯滚,把更多的精力投入到業(yè)務(wù)邏輯上; - 生態(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命令行
- 安裝npm
npm全稱(chēng)為Node Package Manager, 是一個(gè)基于Node . js的包管理器处坪,也是整個(gè)Node . js社區(qū)最流行根资、支持的第三方模塊最多的包管理器。
npm -v 查看npm - 安裝cnpm
npm install -g cnpm -registry=https://registry.npm. taobao.org - 安裝vue一cli
cnpm install -g @vue/cli - 安裝webpack
cnpm install -g webpack
webpack是JavaScript 打包器(module bundler) - 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)目->選擇模板
運(yùn)行
https://uniapp.dcloud.io/quickstart?id=運(yùn)行uni-app
發(fā)布
<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';
}
});
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>
<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"}
- 返回對(duì)象
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)代碼
效果
其他平臺(tái)
微信平臺(tái)
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的按鈕
其他條件編譯的使用場(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快速獲取小程序的能力怖糊,效果如下:
流程
- 原生工程中 添加基礎(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'
}
-
生成小程序應(yīng)用資源伍伤, 在uniapp中制作wgt包
導(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工程中可以看到
安卓工程配置
注意,以下配置項(xiàng)必須添加劝评,并且按照要求填寫(xiě)姐直,否則不停報(bào)錯(cuò)
在原生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中選擇云端插件
-
在插件市場(chǎng)導(dǎo)入
-
回到HBuilderX中導(dǎo)入插件
-
自定義基座
打包完成之后,按照插件使用說(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>
<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模塊
- 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文件
-
5 配置package.json
6 將插件集成到項(xiàng)目中
項(xiàng)目根目錄下新建nativeplugins文件夾膨处,將package.json放入此目錄,新建android文件夾放入安卓打包aar文件砂竖,新建ios文件夾配置放置ios打包.a文件-
7 manifest文件中配置本地模塊
-
8 制作自定義基座(云打包)
-
9 等待打包完成真椿,在需要使用的地方調(diào)用插件即可
-
10 在真機(jī)或模擬器上運(yùn)行,點(diǎn)擊加載fragment按鈕乎澄,效果如下
<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í)
- 整包更新解恰,即常規(guī)的整個(gè)App安裝包重新下載安裝。(不是熱更新)
- 資源熱更新浙于,即App不需要重新安裝护盈,里面的js等前端代碼進(jìn)行更新。(是熱更新)
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)似的原理
<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的使用