APP端開發(fā)注意事項(xiàng)
1、運(yùn)行原理
uni-app
在非H5端運(yùn)行時,從架構(gòu)上分為邏輯層和視圖層兩個部分。邏輯層負(fù)責(zé)執(zhí)行業(yè)務(wù)邏輯,也就是運(yùn)行js代碼,視圖層負(fù)責(zé)頁面渲染。
雖然開發(fā)者在一個vue頁面里寫js和css,但其實(shí),編譯時就已經(jīng)將它們拆分。
邏輯層
運(yùn)行在一個獨(dú)立的jscore里的,它不依賴于本機(jī)的webview
- 無法運(yùn)行window、document、navigator、localstorage等瀏覽器專用的js API
-
jscore
就是一個標(biāo)準(zhǔn)js引擎,標(biāo)準(zhǔn)js是可以正常運(yùn)行的,uni-app的App端和小程序端的js引擎,其實(shí)是在jscore上補(bǔ)充了一批手機(jī)端常用的JS API
<img src="https://img.cdn.aliyun.dcloud.net.cn/uni-app/jscore.jpg" alt="img" style="zoom:40%;" />
視圖層
h5和小程序平臺,以及app-vue,視圖層是webview。而app-nvue的視圖層是基于weex改造的原生渲染視圖。
關(guān)于webview,iOS上默認(rèn)是WKWebview,Android在APP端默認(rèn)是Android system webview,因此app-vue會有手機(jī)瀏覽器的css兼容問題
邏輯層和視圖層分離的利與弊
- 窗體動畫穩(wěn)
- js運(yùn)算不卡渲染
- 兩層互相通信,有通信損耗
- 不管小程序還是app,不管app-vue還是app-nvue,都有這個兩層通信損耗的問題
- 解決方案
優(yōu)化建議
- 使用nvue代替vue
- 使用v3編譯模式,fast啟動模式
- 避免使用大量大圖
- 優(yōu)化數(shù)據(jù)更新,定義在data里面的數(shù)據(jù)盡量是視圖層需要的
- 減少一次性渲染的節(jié)點(diǎn)數(shù)量,比如分批加載數(shù)據(jù)
- 減少組件數(shù)量、減少節(jié)點(diǎn)嵌套層級
- 組件的設(shè)計(jì)策略:復(fù)用,頻繁數(shù)據(jù)更新
- 避免視圖層和邏輯層頻繁進(jìn)行通訊
- 減少 scroll-view 組件的 scroll 事件監(jiān)聽,當(dāng)監(jiān)聽 scroll-view 的滾動事件時,視圖層會頻繁的向邏輯層發(fā)送數(shù)據(jù);
- 監(jiān)聽 scroll-view 組件的滾動事件時,不要實(shí)時的改變 scroll-top/scroll-left 屬性,因?yàn)楸O(jiān)聽滾動時,視圖層向邏輯層通訊,改變 scroll-top/scroll-left 時,邏輯層又向視圖層通訊,這樣就可能造成通訊卡頓。
- 注意 onPageScroll 的使用,onPageScroll 進(jìn)行監(jiān)聽時,視圖層會頻繁的向邏輯層發(fā)送數(shù)據(jù);
- 多使用css動畫,而不是通過js的定時器操作界面做動畫
- 如需在canvas里做跟手操作,app端建議使用renderjs,小程序端建議使用web-view組件。web-view里的頁面沒有邏輯層和視圖層分離的概念,自然也不會有通信折損。
- 優(yōu)化頁面切換動畫
- 頁面初始化時若存在大量圖片或原生組件渲染和大量數(shù)據(jù)通訊,建議延時100ms~300ms
- App-nvue和H5,還支持頁面預(yù)載`uni.preloadPage
2、事件監(jiān)聽與頁面通訊
uni.$emit(eventName,OBJECT)
觸發(fā)全局的自定事件。附加參數(shù)都會 傳給監(jiān)聽器回調(diào)。
屬性 | 類型 | 描述 |
---|---|---|
eventName | String | 事件名 |
OBJECT | Object | 觸發(fā)事件攜帶的附加參數(shù) |
代碼示例
uni.$emit('update',{msg:'頁面更新'})
uni.$on(eventName,callback)
監(jiān)聽全局的自定義事件。事件可以由 uni.$emit 觸發(fā),回調(diào)函數(shù)會接收所有傳入事件觸發(fā)函數(shù)的額外參數(shù)。
uni.$once(eventName,callback)
監(jiān)聽全局的自定義事件。事件可以由 uni.$emit 觸發(fā),但是只觸發(fā)一次,在第一次觸發(fā)之后移除監(jiān)聽器。
屬性 | 類型 | 描述 |
---|---|---|
eventName | String | 事件名 |
callback | Function | 事件的回調(diào)函數(shù) |
代碼示例
uni.$on('update',function(data){
console.log('監(jiān)聽到事件來自 update ,攜帶參數(shù) msg 為:' + data.msg);
})
uni.$once('login',function(data){
console.log('監(jiān)聽到事件來自 login (只觸發(fā)一次),攜帶參數(shù) msg 為:' + data.msg);
})
uni.$off([eventName, callback])
移除全局自定義事件監(jiān)聽器。
屬性 | 類型 | 描述 |
---|---|---|
eventName | Array<String> | 事件名 |
callback | Function | 事件的回調(diào)函數(shù) |
Tips
- 如果沒有提供參數(shù),則移除所有的事件監(jiān)聽器;
- 如果只提供了事件,則移除該事件所有的監(jiān)聽器;
- 如果同時提供了事件與回調(diào),則只移除這個回調(diào)的監(jiān)聽器;
- 提供的回調(diào)必須跟$on的回調(diào)為同一個才能移除這個回調(diào)的監(jiān)聽器;
uni.onUserCaptureScreen(CALLBACK)
監(jiān)聽用戶主動截屏事件,用戶使用系統(tǒng)截屏按鍵截屏?xí)r觸發(fā)此事件。
平臺差異說明
App | H5 | 微信小程序 | 支付寶小程序 | 百度小程序 | 字節(jié)跳動小程序 | QQ小程序 |
---|---|---|---|---|---|---|
x | x | √ | √ | √ | √ | √ |
uni.onNetworkStatusChange(CALLBACK)
監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化。可使用uni.offNetworkStatusChange
取消監(jiān)聽。
uni.offNetworkStatusChange(CALLBACK)
取消監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化。
CALLBACK 返回參數(shù)
參數(shù) | 類型 | 說明 | 平臺差異說明 |
---|---|---|---|
isConnected | Boolean | 當(dāng)前是否有網(wǎng)絡(luò)連接 | 字節(jié)跳動小程序不支持 |
networkType | String | 網(wǎng)絡(luò)類型 |
3、關(guān)于 App 的調(diào)試debug
APP調(diào)試器
console.log打印日志
同步斷點(diǎn)到調(diào)試器代碼調(diào)試
如果是調(diào)試
App
的界面和常規(guī)API,推薦編譯到H5端
關(guān)于Weex 頁面的渲染
圖中畫出了 Weex SDK 的部分內(nèi)容。其中 weex-vue-framework
和 Vue.js
是對等的,語法和內(nèi)部機(jī)制都是一樣的,只不過 Vue.js
最終創(chuàng)建的是 DOM 元素,而 weex-vue-framework
則是向原生端發(fā)送渲染指令,最終渲染生成的是原生組件。Weex Runtime 用來對接上層前端框架(如 Vue.js 和 Rax)并且負(fù)責(zé)和原生端之間的通信。Render Engine 就是針對各個端開發(fā)的原生渲染器,包含了 Weex 內(nèi)置組件和模塊的實(shí)現(xiàn),可擴(kuò)展。
Patch
在 Vue.js 內(nèi)部,Web 平臺和 Weex 平臺中的 patch
方法是不同的,但是都是由 createPatchFunction
這個方法生成的,它支持傳遞 nodeOps
參數(shù),在其中代理了所有 DOM 操作。在 Web 平臺中 nodeOps
背后調(diào)用的都是 Web API,在 Weex 平臺中則調(diào)用的是 Weex Runtime 提供的 Native DOM API。觸發(fā) DOM 渲染的入口一致,但是不同平臺的實(shí)現(xiàn)方式不同。
上層前端框架調(diào)用了 Weex 平臺提供的 Native DOM API 之后,Weex Runtime 會構(gòu)建一個用于渲染的節(jié)點(diǎn)樹,并將操作轉(zhuǎn)換成渲染指令發(fā)送給客戶端
目前來說渲染指令是基于 JSON 描述的,具體格式大致如下所示:
{
module: 'dom',
method: 'createBody',
args: [{
ref: '_root',
type: 'div',
style: { justifyContent: 'center' }
}]
}
原生渲染器接收上層傳來的渲染指令,并且逐步將其渲染成原生組件。