前段時間學習了關於vue中響應式數據的原理,(並做了學習筆記vue響應式原理),實際上是經過Object.defineProperty
控制getter和setter,並利用觀察者模式完成的響應式設計。那麼數組有一系列的操做方法,這些方法並不會觸發數組的getter和setter方法。那麼vue中針對數組的響應式設計是如何實現的呢...那麼咱們一塊兒去學習下吧~html
https://github.com/vuejs/vue/blob/dev/src/core/observer/array.jsvue
Emmmm...
我以爲要先把Vue中的數據響應式原理弄清楚,這樣對於理解vue中是如何檢測數組的變化才比較好,因此,能夠去網上找下文章而後配合源碼進行閱讀,相信你必定會理解的。推薦下我以前看的一篇博客,還有我看事後本身寫的學習記錄吧,哈哈。git
好的,先看看這個吧。哈哈!github
我們先看下下面的圖,先了解下vue中實現的思路,這樣接下來再看源碼的實現,會一清二楚,明明白白。
segmentfault
看到這個圖而後思考一下,是否是大體瞭解了~數組
是否是很簡單!!!瀏覽器
瞭解了實現原理,那麼咱們再看看源碼吧,看下源碼主要是更深刻的瞭解做者是如何實現的,也能夠看下優秀的代碼編碼方式,加以學習。緩存
關於一些解釋我就寫在下面的代碼塊中了哈!app
//https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js //def方法是基於Object.defineProperty封裝的一層方法,很簡單,我會在下面把代碼貼出來,省得你們去找了。 import { def } from '../util/index' //保存下原生的數組原型對象 const arrayProto = Array.prototype //進行原型鏈接,將arrayMethods的原型指向Array.prototype export const arrayMethods = Object.create(arrayProto) const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] methodsToPatch.forEach(function (method) { // 緩存原生的方法 const original = arrayProto[method] def(arrayMethods, method, function mutator (...args) { var args = [], len = arguments.length; while (len--) args[len] = arguments[len]; const result = original.apply(this, args) // 原來的數組方法執行結果 const ob = this.__ob__ // 這個__ob__就是Observe的實例~~~~ let inserted switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } if (inserted) ob.observeArray(inserted) // 若是數組有變化,則從新調用observeArray // notify change ob.dep.notify() // return result }) })
這個是關於Observe
的代碼:學習
var Observer = function Observer(value) { this.value = value; this.dep = new Dep(); this.vmCount = 0; def(value, '__ob__', this); //這裏會看到在每一個對象數據上都會綁定一個Observe的實例,因此上面代碼中的this.__ob__就是這個 if (Array.isArray(value)) { // 這裏判斷是不是數組類型的數據,若是是的話就走observeArray if (hasProto) { protoAugment(value, arrayMethods); } else { copyAugment(value, arrayMethods, arrayKeys); } this.observeArray(value); //這裏就是處理數組類型的數據,以下 } else { this.walk(value); } };
以下是observeArray
的實現:
Observer.prototype.observeArray = function observeArray(items) { for (var i = 0, l = items.length; i < l; i++) { observe(items[i]); // 這個observe方法以下 } };
在這裏咱們看下observe
這個方法:
function observe(value, asRootData) { if (!isObject(value) || value instanceof VNode) { return } var ob; if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__; } else if ( shouldObserve && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { ob = new Observer(value); } if (asRootData && ob) { ob.vmCount++; } return ob }
這個是關於def
方法的實現,很簡單我就不說了哈:
function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); }
就這麼多吧...也沒講什麼,大體看下整理出來的核心代碼,應該就能夠了解它實現的思路了吧...等我研究透了再更新下,就這樣吧..