《深入浅出vue.js》阅读笔记之数组变化侦测
?
?
1、如何追蹤變化
數組的偵測方式和對象不同,比如:
this.list.push(1)
此時并不會像改變對象一樣觸發setter。
同理,要偵測數組的變化意味著我們在改變數組的時候得到通知,如圖,我們可以用一個攔截器覆蓋Array.prototype,每當使用array原型方法時,實際
執行的是攔截器中的方法,而攔截器中的方法儲存原生方法實現。
2、實現攔截器
攔截器其實是一個和Array.prototype一樣的object,只不過這個object中某些可以改變數組自身內容的方法是處理過的。
改變數組內容的方法一共有七個,push,pop,shift, unshiftj, slice, sort 和reverse
const arrayProto = Array.prototype const arrayMethods = Object.create(arrayProto) const methods = ['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse'] methods.forEach(function (method) {// 緩存原始方法const original = arrayProto[method]Object.defineProperty(arrayMethods, method, {value: function mutator (...args) {return original.apply(this, args)},enumerable: false,writable: true,configurable: true,}) })上面代碼中,arrayMethods繼承自Array.prototype,具備其所有功能。當使用push方法時,調用的是arrayMethods.push,即mutator函數,這里可以做一些發送通知
變化之類的事情。
3、使用攔截器覆蓋Array原型
有了攔截器,就需要讓它覆蓋Array.prototype,但又不能直接覆蓋,因為會污染全局變量Array,我們希望只是攔截那些被偵測了變化的數據生效。
這時就需要借助Observer
class Observer {constructor (value) {this.value = value}if (Array.isArray(value)) {value.__proto__ = arrayMethods} else {this.walk(value)} }它的作用是將攔截器(加工后具備攔截功能的arrayMethods)賦值給value.__proto__,通過__proto__巧妙的實現覆蓋value原型功能。
__proto__其實是Object.getPrototypeOf和Object.setPrototypeOf的早期實現,所以使用es6的Object.setPrototypeOf來代替__ptoto__可以實現同樣的效果。
4、將攔截器方法掛載到數組屬性上
雖然絕大多數瀏覽器都支持這個非標準的屬性來訪問原型,但并不是所有瀏覽器都支持,因此需要處理不能使用__proto__的情況。
vue的做法是對于不能使用__proto__的,直接將arrayMethods身上的這些方法設置到被偵測的數組上。
export class Object {if (Array.isArray(value)) {const augment = hasProto ? protoAugment : copyAugmentaugment(value, arrayMethods, arrayKeys)} else {this.walk(value)} }function protoAugment (target, src, keys) {target.__proto__ = src }function copyAugment (target, src, keys) {for (let i=0, len = keys.lenght;i< 1; i++) {const key = keys[i]default(target, key, src[key])} }在上面代碼中,新增了hasProto來判斷當前瀏覽器是否支持__proto__,如果支持,則使用protoAugment覆蓋原型,否則用copyAugment將攔截器中的方法掛載到value。
copyAugment函數用來將已經加工了攔截操作的原型方法直接添加到value的屬性中。
?
轉載于:https://www.cnblogs.com/pjl43/p/10666448.html
總結
以上是生活随笔為你收集整理的《深入浅出vue.js》阅读笔记之数组变化侦测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS7完成mysql的安装和远程
- 下一篇: Vue 组件间通信六种方式