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
視圖層
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端
4蟹但、 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ò)展。
5超棺、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' }
}]
}
原生渲染器接收上層傳來的渲染指令对扶,并且逐步將其渲染成原生組件。