《深入浅出vue.js》阅读笔记之数组变化侦测
?
?
1、如何追蹤變化
數(shù)組的偵測(cè)方式和對(duì)象不同,比如:
this.list.push(1)
此時(shí)并不會(huì)像改變對(duì)象一樣觸發(fā)setter。
同理,要偵測(cè)數(shù)組的變化意味著我們?cè)诟淖償?shù)組的時(shí)候得到通知,如圖,我們可以用一個(gè)攔截器覆蓋Array.prototype,每當(dāng)使用array原型方法時(shí),實(shí)際
執(zhí)行的是攔截器中的方法,而攔截器中的方法儲(chǔ)存原生方法實(shí)現(xiàn)。
2、實(shí)現(xiàn)攔截器
攔截器其實(shí)是一個(gè)和Array.prototype一樣的object,只不過這個(gè)object中某些可以改變數(shù)組自身內(nèi)容的方法是處理過的。
改變數(shù)組內(nèi)容的方法一共有七個(gè),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,具備其所有功能。當(dāng)使用push方法時(shí),調(diào)用的是arrayMethods.push,即mutator函數(shù),這里可以做一些發(fā)送通知
變化之類的事情。
3、使用攔截器覆蓋Array原型
有了攔截器,就需要讓它覆蓋Array.prototype,但又不能直接覆蓋,因?yàn)闀?huì)污染全局變量Array,我們希望只是攔截那些被偵測(cè)了變化的數(shù)據(jù)生效。
這時(shí)就需要借助Observer
class Observer {constructor (value) {this.value = value}if (Array.isArray(value)) {value.__proto__ = arrayMethods} else {this.walk(value)} }它的作用是將攔截器(加工后具備攔截功能的arrayMethods)賦值給value.__proto__,通過__proto__巧妙的實(shí)現(xiàn)覆蓋value原型功能。
__proto__其實(shí)是Object.getPrototypeOf和Object.setPrototypeOf的早期實(shí)現(xiàn),所以使用es6的Object.setPrototypeOf來代替__ptoto__可以實(shí)現(xiàn)同樣的效果。
4、將攔截器方法掛載到數(shù)組屬性上
雖然絕大多數(shù)瀏覽器都支持這個(gè)非標(biāo)準(zhǔn)的屬性來訪問原型,但并不是所有瀏覽器都支持,因此需要處理不能使用__proto__的情況。
vue的做法是對(duì)于不能使用__proto__的,直接將arrayMethods身上的這些方法設(shè)置到被偵測(cè)的數(shù)組上。
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來判斷當(dāng)前瀏覽器是否支持__proto__,如果支持,則使用protoAugment覆蓋原型,否則用copyAugment將攔截器中的方法掛載到value。
copyAugment函數(shù)用來將已經(jīng)加工了攔截操作的原型方法直接添加到value的屬性中。
?
轉(zhuǎn)載于:https://www.cnblogs.com/pjl43/p/10666448.html
總結(jié)
以上是生活随笔為你收集整理的《深入浅出vue.js》阅读笔记之数组变化侦测的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS7完成mysql的安装和远程
- 下一篇: IDEA打开父类的接口方法快捷键