告訴元首我已盡力,告訴父親我仍然愛他!html
熟悉 Vue 的同窗對 computed
和 watch
必定很熟悉,這些特性大大方便了咱們對代碼中的數據進行處理:前端
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 計算屬性的 getter
reversedMessage: function () {
// `this` 指向 vm 實例
return this.message.split('').reverse().join('')
}
}
})
複製代碼
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
複製代碼
這是 Vue 官網中兩段代碼。git
現在小程序也有了本身的實現,詳見官方文檔 observer 。小程序官方 github 中也開源了經過 Behaviors 實現的 Vue 風格的computed
和watch
:github.com/wechat-mini…。github
那麼在微信沒有提供這些方法以前,如何自主實現數據的偵聽器和計算屬性呢?小程序
先看看定義的使用文檔:緩存
Page({
data: {
list: [],
list2: [],
size: 0
},
// 偵聽器函數名必須跟須要被偵聽的 data 對象中的屬性同名,
// 其參數中的 newValue 爲屬性改變後的新值,oldValue 爲改變前的舊值
watch: {
// 若是 `list` 發生改變,這個函數就會運行
list(newValue, oldValue) {
console.log(oldValue + '=>' + newValue)
}
},
// 傳入的參數list必須是 data 裏面的屬性
// 這裏能夠傳入多個 data 屬性
computed({
list,
list2
}) {
return {
size: list.length,
size2: list2.length
}
}
})
複製代碼
在 Page
的傳參中多了兩個熟悉的屬性,用法不用解釋太多。須要繼續對小程序提供的 Page
方法進行改造,此外,由於全部數據變化都會用到 setData
方法去觸發,因此還須要改造這個方法。微信
想要基於原有的 setData
進行封裝,那就得先獲得這個函數緩存下來(像是緩存原有的 Page
同樣)。想到 onLoad
是小程序頁面的第一個生命週期函數,能夠在這裏進行操做:app
// 緩存原有的 `Page`
let originPage = Page
// 定義新的 Page
function MyPage(config) {
let that = this
this.watch = config.watch
this.computed = config.computed
this.lifetimeBackup = {
onLoad: config.onLoad
}
config.onLoad = function(options) {
// 緩存下原有的 `setData`
this._setData = this.setData.bind(this)
this.setData = (data) => {
// 偵聽器
that.watching(data)
// 計算器
let newData = that.getComputedData(data)
this._setData(extend(data, newData))
}
// 備份下頁面實例
that.context = this
// 執行真正的 `onLoad`
this.lifetimeBackup.onLoad.call(this, options)
}
// ...
originPage(config)
}
MyPage.prototype.watching = funtion(data) {
// 執行偵聽器
// ...
}
// 計算器
MyPage.prototype.getComputedData = function(data) {
// 開始生成新的數據
// ...
}
function page (config) {
return new MyPage(config)
}
複製代碼
大體代碼如上,從新定義了 this.setData
,備份了原有的 setData
到 this._setData
。固然,這裏只考慮了 setData
傳一個參數的狀況,多個參數須要再對代碼優化下。框架
注意:調用 watching
和 createNewData
的對象是 that
,由於 this
指向小程序頁面實例,沒有自定的這個方法。函數
作完上述改造,後續的 watch
和 computed
就簡單多了。
MyPage.prototype.watching = function(data) {
var context = this.context
var oldData = context.data
// 開始生成新的數據
var watch = this.watch
if (watch) {
Object.keys(watch).forEach(function (k) {
// 若是新的 data 中屬性被偵聽,執行偵聽函數
if (k in data) {
var newValue = data[k]
var oldValue = oldData[k]
watch[k].apply(context, [
newValue,
oldValue
])
}
})
}
}
複製代碼
簡易的偵聽器就寫好了,經過 setData
觸發自定的 watch 中的偵聽函數。
MyPage.prototype.getComputedData = function(data) {
var context = this.context
var computed = this.computed
var computedData
if (computed) {
computedData = computed.call(context, data)
}
return computedData
}
複製代碼
這樣就獲得了計算後的新生成的數據:computedData
。
不斷的經過備份、代理微信原有的方法,自主實現了簡單的偵聽器和計算器。固然這些代碼只是爲了方便分享提取出來了提供思路,實際業務中遇到狀況複雜的多,代碼量遠遠也不止這些。
美團單車事業部(摩拜單車)誠招前端 / 小程序研發工程師,位置北京,有興趣能夠發簡歷到 zhangshibing@mobike.com 或者掃二維碼先加微信勾搭:)