APP端開發(fā)注意事項(xiàng)
1没陡、運(yùn)行原理
uni-app
在非H5端運(yùn)行時(shí)泡仗,從架構(gòu)上分為邏輯層和視圖層兩個(gè)部分梦染。邏輯層負(fù)責(zé)執(zhí)行業(yè)務(wù)邏輯赡麦,也就是運(yùn)行js代碼,視圖層負(fù)責(zé)頁面渲染帕识。
雖然開發(fā)者在一個(gè)vue頁面里寫js和css泛粹,但其實(shí),編譯時(shí)就已經(jīng)將它們拆分渡冻。
邏輯層
運(yùn)行在一個(gè)獨(dú)立的jscore里的戚扳,它不依賴于本機(jī)的webview
- 無法運(yùn)行window忧便、document族吻、navigator、localstorage等瀏覽器專用的js API
-
jscore
就是一個(gè)標(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和小程序平臺(tái)蒂教,以及app-vue巍举,視圖層是webview。而app-nvue的視圖層是基于weex改造的原生渲染視圖凝垛。
關(guān)于webview懊悯,iOS上默認(rèn)是WKWebview,Android在APP端默認(rèn)是Android system webview梦皮,因此app-vue會(huì)有手機(jī)瀏覽器的css兼容問題
邏輯層和視圖層分離的利與弊
- 窗體動(dòng)畫穩(wěn)
- js運(yùn)算不卡渲染
- 兩層互相通信炭分,有通信損耗
- 不管小程序還是app,不管app-vue還是app-nvue剑肯,都有這個(gè)兩層通信損耗的問題
- 解決方案
優(yōu)化建議
- 使用nvue代替vue
- 使用v3編譯模式而账,fast啟動(dòng)模式
- 避免使用大量大圖
- 優(yōu)化數(shù)據(jù)更新胰坟,定義在data里面的數(shù)據(jù)盡量是視圖層需要的
- 減少一次性渲染的節(jié)點(diǎn)數(shù)量,比如分批加載數(shù)據(jù)
- 減少組件數(shù)量福扬、減少節(jié)點(diǎn)嵌套層級(jí)
- 組件的設(shè)計(jì)策略:復(fù)用腕铸,頻繁數(shù)據(jù)更新
- 避免視圖層和邏輯層頻繁進(jìn)行通訊
- 減少 scroll-view 組件的 scroll 事件監(jiān)聽,當(dāng)監(jiān)聽 scroll-view 的滾動(dòng)事件時(shí)铛碑,視圖層會(huì)頻繁的向邏輯層發(fā)送數(shù)據(jù)狠裹;
- 監(jiān)聽 scroll-view 組件的滾動(dòng)事件時(shí),不要實(shí)時(shí)的改變 scroll-top/scroll-left 屬性汽烦,因?yàn)楸O(jiān)聽滾動(dòng)時(shí)涛菠,視圖層向邏輯層通訊,改變 scroll-top/scroll-left 時(shí)撇吞,邏輯層又向視圖層通訊俗冻,這樣就可能造成通訊卡頓。
- 注意 onPageScroll 的使用牍颈,onPageScroll 進(jìn)行監(jiān)聽時(shí)迄薄,視圖層會(huì)頻繁的向邏輯層發(fā)送數(shù)據(jù);
- 多使用css動(dòng)畫煮岁,而不是通過js的定時(shí)器操作界面做動(dòng)畫
- 如需在canvas里做跟手操作讥蔽,app端建議使用renderjs,小程序端建議使用web-view組件画机。web-view里的頁面沒有邏輯層和視圖層分離的概念冶伞,自然也不會(huì)有通信折損。
- 優(yōu)化頁面切換動(dòng)畫
- 頁面初始化時(shí)若存在大量圖片或原生組件渲染和大量數(shù)據(jù)通訊步氏,建議延時(shí)100ms~300ms
- App-nvue和H5响禽,還支持頁面預(yù)載`uni.preloadPage
2、事件監(jiān)聽與頁面通訊
uni.$emit(eventName,OBJECT)
觸發(fā)全局的自定事件荚醒。附加參數(shù)都會(huì) 傳給監(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ù)會(huì)接收所有傳入事件觸發(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)聽器;
- 如果同時(shí)提供了事件與回調(diào)弓颈,則只移除這個(gè)回調(diào)的監(jiān)聽器帽芽;
- 提供的回調(diào)必須跟$on的回調(diào)為同一個(gè)才能移除這個(gè)回調(diào)的監(jiān)聽器;
uni.onUserCaptureScreen(CALLBACK)
監(jiān)聽用戶主動(dòng)截屏事件翔冀,用戶使用系統(tǒng)截屏按鍵截屏?xí)r觸發(fā)此事件导街。
平臺(tái)差異說明
App | H5 | 微信小程序 | 支付寶小程序 | 百度小程序 | 字節(jié)跳動(dòng)小程序 | 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ù) | 類型 | 說明 | 平臺(tái)差異說明 |
---|---|---|---|
isConnected | Boolean | 當(dāng)前是否有網(wǎng)絡(luò)連接 | 字節(jié)跳動(dòng)小程序不支持 |
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
是對(duì)等的卡乾,語法和內(nèi)部機(jī)制都是一樣的翼悴,只不過 Vue.js
最終創(chuàng)建的是 DOM 元素,而 weex-vue-framework
則是向原生端發(fā)送渲染指令幔妨,最終渲染生成的是原生組件鹦赎。Weex Runtime 用來對(duì)接上層前端框架(如 Vue.js 和 Rax)并且負(fù)責(zé)和原生端之間的通信。Render Engine 就是針對(duì)各個(gè)端開發(fā)的原生渲染器陶冷,包含了 Weex 內(nèi)置組件和模塊的實(shí)現(xiàn)钙姊,可擴(kuò)展毯辅。
Patch
在 Vue.js 內(nèi)部埂伦,Web 平臺(tái)和 Weex 平臺(tái)中的 patch
方法是不同的,但是都是由 createPatchFunction
這個(gè)方法生成的思恐,它支持傳遞 nodeOps
參數(shù)沾谜,在其中代理了所有 DOM 操作。在 Web 平臺(tái)中 nodeOps
背后調(diào)用的都是 Web API胀莹,在 Weex 平臺(tái)中則調(diào)用的是 Weex Runtime 提供的 Native DOM API基跑。觸發(fā) DOM 渲染的入口一致,但是不同平臺(tái)的實(shí)現(xiàn)方式不同描焰。
上層前端框架調(diào)用了 Weex 平臺(tái)提供的 Native DOM API 之后媳否,Weex Runtime 會(huì)構(gòu)建一個(gè)用于渲染的節(jié)點(diǎn)樹栅螟,并將操作轉(zhuǎn)換成渲染指令發(fā)送給客戶端
目前來說渲染指令是基于 JSON 描述的,具體格式大致如下所示:
{
module: 'dom',
method: 'createBody',
args: [{
ref: '_root',
type: 'div',
style: { justifyContent: 'center' }
}]
}
原生渲染器接收上層傳來的渲染指令篱竭,并且逐步將其渲染成原生組件力图。