W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
了解常用的優(yōu)化手段,提升對(duì)應(yīng)用代碼整理的組織能力,合理拆分功能模塊
通過(guò)本節(jié),你將學(xué)會(huì):
教程文檔對(duì)應(yīng)的項(xiàng)目代碼文件:src/Optimization目錄
框架應(yīng)用開發(fā)與傳統(tǒng)的H5頁(yè)面開發(fā)之間有一個(gè)顯著的不同點(diǎn):
應(yīng)用是多頁(yè)面共享同一個(gè)V8 Context,而H5頁(yè)面通常是一個(gè)頁(yè)面一個(gè)V8 Context,頁(yè)面間無(wú)法通訊
因此,在應(yīng)用開發(fā)中,開發(fā)者需要了解頁(yè)面與APP之間,頁(yè)面與頁(yè)面之間的數(shù)據(jù)共享方式。常見的通訊需求如下:
目前,在框架中,可以通過(guò)使用框架API
實(shí)現(xiàn)數(shù)據(jù)共享
開發(fā)者可以在頁(yè)面ViewModel
中,通過(guò)this.$app.$def
獲取APP上定義的數(shù)據(jù)及方法。詳見文檔生命周期
示例如下:
// app.ux中導(dǎo)出的對(duì)象
const appDef = this.$app.$def
性能優(yōu)化包括兩個(gè)大類
建議開發(fā)者了解性能優(yōu)化的常見方案,提升應(yīng)用性能
ViewModel
的數(shù)據(jù)在ViewModel
的定義中,屬性public
、protected
、private
主要承擔(dān)數(shù)據(jù)驅(qū)動(dòng)的數(shù)據(jù)定義與改造功能,會(huì)對(duì)賦值的數(shù)據(jù)中每個(gè)屬性進(jìn)行遞歸式的定義。因此,屬性個(gè)數(shù)的定義越少越好,尤其是數(shù)組類型數(shù)據(jù),建議過(guò)濾不需要用到的對(duì)象屬性
示例如下:
如果頁(yè)面僅需要用到list中每個(gè) item 的 userId,orderName 屬性的話,則僅賦值這兩個(gè)屬性到ViewModel
數(shù)據(jù)中,過(guò)濾掉非相關(guān)屬性:
// 模擬fetch請(qǐng)求返回的數(shù)據(jù)
const orderList = [
{
userId: '123',
orderName: 'XX產(chǎn)品',
userName: '張三',
shoppingList: [
{
productId: '001',
productLink: 'http://xxx',
productShop: {
ownerId: '2390',
ownerName: 'XXX店鋪'
}
}
]
},
{
// ...
}
]
export default {
data () {
return {
list: []
}
},
onInit () {
// 返回頁(yè)面中需要的對(duì)象屬性,過(guò)濾無(wú)用的對(duì)象屬性
this.list = orderList.map(item => {
userId: item.userId,
orderName: item.orderName
})
}
}
框架支持 CSS 中的后代選擇、支持 less 預(yù)編譯,方便開發(fā)者開發(fā),提升代碼可維護(hù)性。然而,過(guò)多的使用后代選擇器,也會(huì)在節(jié)點(diǎn)匹配上帶來(lái)性能損耗,尤其是當(dāng)一個(gè)節(jié)點(diǎn)滿足多個(gè)選擇時(shí)
優(yōu)化建議如下:
.doc-page #shop text { ... }
;否則每個(gè)text組件渲染時(shí)都會(huì)遍歷匹配一次.class1 .class2 .class3 .class4 .class5 .class6 { ... }
.doc-page #shop .shop-item .shop-name-full { ... }
懶加載是一項(xiàng)通用的優(yōu)化手段,傳統(tǒng)H5頁(yè)面中的圖片懶加載,指的是頁(yè)面即將滾動(dòng)到屏幕可視區(qū)域時(shí),才加載資源,渲染頁(yè)面
在框架中,也可以使用懶加載技術(shù):為了加快頁(yè)面可視區(qū)域的渲染,可以通過(guò)指令
或者事件觸發(fā)
等手段推遲不可見區(qū)域的渲染
例如:
if
指令控制tab-content組件的子節(jié)點(diǎn)
)。詳見文檔tabs教程
在框架的開發(fā)中,一旦程序執(zhí)行出錯(cuò),就會(huì)報(bào)出 JS 異常彈框。常見的一些錯(cuò)誤有:
場(chǎng)景舉例:
這是 JS 開發(fā)中常見的錯(cuò)誤。對(duì)一個(gè)值為 null 或 undefined 的變量取屬性就會(huì)報(bào)錯(cuò)。例如:
<!-- a = {}; -->
<text>{{ a.b.c }}</text>
<!-- Error: Cannot read property 'c' of undefined -->
解決方案:
1、&& 方法,通過(guò)邏輯運(yùn)算的執(zhí)行順序來(lái)規(guī)避錯(cuò)誤。代碼如下:
<text>{{ a && a.b && a.b.c }}</text>
2、 在 ViewModel 上增加函數(shù)方法
推薦方案 2,在 ViewModel 上建立一個(gè) checkEmpty 函數(shù)。示例代碼如下:
export default {
checkEmpty(...args) {
let ret
if (args.length > 0) {
ret = args.shift()
let tmp
while (ret && args.length > 0) {
tmp = args.shift()
ret = ret[tmp]
}
}
return ret || false
}
}
這樣,就可以方便的調(diào)用了。
<text>{{checkEmpty(a, 'b', 'c')}}</text>
場(chǎng)景舉例:
代碼執(zhí)行 fetch 請(qǐng)求,請(qǐng)求返回的數(shù)據(jù)默認(rèn)是 JSON 化的字符串了,開發(fā)者使用 JSON 對(duì)象解析,這是正常邏輯;
但是一旦遇到服務(wù)器端權(quán)限校驗(yàn)失敗等問(wèn)題時(shí),會(huì)返回類似 503 的 HTML 頁(yè)面,此時(shí) JSON 解析肯定就會(huì)失敗
解決方案:
推薦方案2,示例代碼如下:
export function parseProxy () {
const rawParse = JSON.parse
JSON.parse = function (str, defaults) {
try {
return rawParse(str)
}
catch (err) {
console.error(`JSON解析失敗:${str}, ${err.stack}`)
return defaults
}
}
}
ViewModel
數(shù)據(jù)報(bào)錯(cuò)場(chǎng)景舉例:
用戶打開 PageA,然后點(diǎn)擊鏈接打開 PageB,PageB 中執(zhí)行接口方法(如 fetch 請(qǐng)求),然后立即返回到 PageA;此時(shí)接口的回調(diào)函數(shù)返回,但 PageB 已經(jīng)出棧銷毀,此時(shí),執(zhí)行開發(fā)者傳遞的回調(diào)函數(shù)報(bào)錯(cuò)
這是由于,回調(diào)函數(shù)中訪問(wèn)了一些data數(shù)據(jù)等,而這些ViewModel
的數(shù)據(jù)屬性已經(jīng)伴隨著頁(yè)面銷毀而刪除了,所以引起報(bào)錯(cuò)
報(bào)錯(cuò)信息為:undefined:217: TypeError: Cannot read property 'xx' of null
解決方案:
1.在回調(diào)函數(shù)執(zhí)行之前,通過(guò)ViewModel
對(duì)象的$valid
、$visible
判斷頁(yè)面狀態(tài)
2.在Function.prototype
上定義方法,關(guān)聯(lián)到每個(gè)回調(diào)函數(shù)綁定ViewModel
實(shí)例
推薦方案2,示例代碼如下:
/**
* 在Function原型上定義bindPage方法:將回調(diào)函數(shù)綁定到頁(yè)面對(duì)象,頁(yè)面不可見或者銷毀時(shí),不執(zhí)行回調(diào)函數(shù)
*/
export function bindPageLC () {
Function.prototype.bindPage = function (vmInst) {
const fn = this
return function () {
if (!vmInst) {
throw new Error(`使用錯(cuò)誤:請(qǐng)傳遞VM對(duì)象`)
}
if (vmInst.$valid && vmInst.$visible) {
return fn(...arguments)
}
else {
console.info(`頁(yè)面不可見或者銷毀時(shí),不執(zhí)行回調(diào)函數(shù)`)
}
}
}
}
在${anyPage}.ux
中,通過(guò)fn.bindPage(this)
,在回調(diào)函數(shù)上綁定ViewModel
實(shí)例
export default {
data () {
return {}
},
request () {
// 調(diào)用bindPage(this)返回:綁定了頁(yè)面對(duì)象的回調(diào)函數(shù),當(dāng)頁(yè)面不可見或者銷毀時(shí),不執(zhí)行回調(diào)函數(shù)
fetch.fetch({
success: function(ret) {
// 數(shù)據(jù)操作等
}.bindPage(this)
})
}
}
示例代碼詳見Tutorial項(xiàng)目
中app.ux文件引入的:util.js
結(jié)構(gòu)優(yōu)化的目的是減小頁(yè)面以及整體rpk包的體積,減少冗余代碼
常用的手段有以下幾項(xiàng):
在app.ux
中引入常用的JS庫(kù),并暴露給每個(gè)頁(yè)面使用;可以避免每個(gè)頁(yè)面在打包時(shí)對(duì)JS的重復(fù)定義
好的優(yōu)化能夠提升項(xiàng)目的可維護(hù)性,保證頁(yè)面渲染的性能,減少不必要的代碼耦合;建議開發(fā)者多多體會(huì)
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: