干貨 | 小程序的小技巧之 computed 計算屬性

小程序的出身,基于安全和管控的考慮,使用了雙線程的設計,同時對于 DOM 操作、動態創建 DOM 這些都隔離了。在寫代碼的時候,模版語法不支持函數計算,computed 的方法就顯得十分重要。

自定義組件

小程序的自定義組件涉及功能很多,這篇只針對computed展開來講。

computed比較適合較復雜邏輯的計算,同時在小程序無法在模板里使用methods這樣的場景下,計算屬性的需求就更強烈了。

behaviors

自定義組件中,提供了behaviors的使用和定義。

從官方文檔我們能看到:

behaviors是用于組件間代碼共享的特性,類似于一些編程語言中的“mixins”或“traits”。
每個behavior可以包含一組屬性、數據、生命周期函數和方法,組件引用它時,它的屬性、數據和方法會被合并到組件中,生命周期函數也會在對應時機被調用。每個組件可以引用多個behavior。
簡單來說,我們能通過behaviors來重構Component的能力。

如果說,我們能“混入”Component,其實基本很多能力都能實現啦。其實我們自己封裝一層的MyComponent也能達到一定的效果,但是這樣的拓展性會變得很糟。

通過behaviors的方式,每個組件可以按需引入自己需要的behavior啦。

computed 實現
我們來梳理下這里的邏輯,我們需要一個computed能力,需要處理的主要是:setData的時候,根據computed來計算哪些數據需要處理。

所以我們要做的是:

記下來需要computed的變量。
在每次setData之前,看看是否包含到需要computed的變量,匹配到了就進行computed處理。
使用處理后的數據,進行setData。
官方已經提供了計算屬性實現的behavior,大家也可以盡情翻看實現的源碼,和使用這種拓展能力。

Page 的超集

hack 實現 Page computed 能力

想必大家都會有疑惑,Component里支持behaviors,但是Page依然寫起來很不方便呀。雖然所有的Page最終也能通過Component來實現,但是這樣是否需要多包裝一層呢?

答案是不用。

使用 Component 構造器構造頁面

Component是Page的超集,因此可以使用Component構造器構造頁面。

同樣的,我們來看看官方文檔:

事實上,小程序的頁面也可以視為自定義組件。因而,頁面也可以使用Component構造器構造,擁有與普通組件一樣的定義段與實例方法。但此時要求對應json文件中包含usingComponents定義段。
也就是說,我們這樣的頁面:

Page({
data: {
logs: []
},
onLoad(query) {
// 如訪問頁面`/pages/index/index?paramA=123&paramB=xyz`,如果聲明有屬性(`properties`)`paramA`或`paramB`,則它們會被賦值為`123`或`xyz`
query.paramA // 頁面參數 paramA 的值
query.paramA // 頁面參數 paramB 的值
this.setData({
logs: (wx.getStorageSync("logs") || []).map((log: number) => {
return formatTime(new Date(log));
})
});
}
});

可以這么寫:

{
"usingComponents": {}
}
Component({
// 組件的屬性可以用于接收頁面的參數
properties: {
paramA: Number,
paramB: String,
},
data: {
logs: []
},
methods: {
onLoad() {
// 如訪問頁面`/pages/index/index?paramA=123&paramB=xyz`,如果聲明有屬性(`properties`)`paramA`或`paramB`,則它們會被賦值為`123`或`xyz`
this.data.paramA // 頁面參數 paramA 的值
this.data.paramB // 頁面參數 paramB 的值
this.setData({
logs: (wx.getStorageSync("logs") || []).map((log: number) => {
return formatTime(new Date(log));
})
});
}
}
});

這樣,我們就能愉快地使用behaviors啦。

const computedBehavior = require("miniprogram-computed");
Component({
behaviors: [computedBehavior],
data: {
logs: []
},
computed: {
logsAfterComputed() {
// 計算屬性同樣掛在 data 上,每當進行 setData 的時候會重新計算
// 比如此字段可以通過 this.data.b 獲取到
return this.data.logs.map(x => {
return {
log: x,
logAfterCompute: x + "logAfterCompute"
};
});
}
},
methods: {
onLoad() {
this.setData({
logs: (wx.getStorageSync("logs") || []).map((log: number) => {
return formatTime(new Date(log));
})
});
}
}
});

使用Component構造器構造頁面,需要注意:

組件的屬性可以用于接收頁面的參數,如訪問頁面/pages/index/index?paramA=123&paramB=xyz,如果聲明有屬性(properties)paramA或paramB,則它們會被賦值為123或xyz。(可參考官方代碼示例)

頁面的生命周期方法(即on開頭的方法,如上面的onLoad),應寫在methods定義段中。

這樣,你就能愉快地在代碼里面使用computed計算屬性啦~

更多的,也可以參考本人的wxapp-typescript-demo中的log page,后續也會持續更新方便好用的能力 demo。

文章來源:騰訊工程師 王貝珊

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容