告訴元首我已盡力,告訴父親我仍然愛他!
熟悉 Vue 的同窗對 computed
和 watch
必定很熟悉,這些特性大大方便了咱們對代碼中的數據進行處理:html
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
:https://github.com/wechat-miniprogram/computed。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
方法去觸發,因此還須要改造這個方法。app
想要基於原有的 setData
進行封裝,那就得先獲得這個函數緩存下來(像是緩存原有的 Page
同樣)。想到 onLoad
是小程序頁面的第一個生命週期函數,能夠在這裏進行操做:函數
// 緩存原有的 `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
指向小程序頁面實例,沒有自定的這個方法。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
。
不斷的經過備份、代理微信原有的方法,自主實現了簡單的偵聽器和計算器。固然這些代碼只是爲了方便分享提取出來了提供思路,實際業務中遇到狀況複雜的多,代碼量遠遠也不止這些。