上一節Vue中的視圖更新原理說到默認的defineProperty能夠攔截到經過數組下標方式修改的值的變動,可是Vue中爲了更好的性能和用戶體驗而對數組單獨進行了處理,那Vue中到底是如何來處理的呢?vue
vue源碼以下:segmentfault
var arrayProto = Array.prototype; var arrayMethods = Object.create(arrayProto); var methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ]; /** * Intercept mutating methods and emit events */ methodsToPatch.forEach(function (method) { // cache original method var original = arrayProto[method]; def(arrayMethods, method, function mutator () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; var result = original.apply(this, args); var ob = this.__ob__; var inserted; switch (method) { case 'push': case 'unshift': inserted = args; break case 'splice': inserted = args.slice(2); break } if (inserted) { ob.observeArray(inserted); } // notify change ob.dep.notify(); return result }); });
/** * Define a property. */ function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); }
也就是說vue中基於原生Array的原型對象建立了一個新對象,從新定義了數組中的如下方法:數組
'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'
將以上方法定義經過defineProperty定義成了響應式, 對於push、unshift、splice方法給數組新增值時還作了特別的處理。在vue中直接操做以上方法修改數組值,視圖都能響應。app
Object.defineProperty做爲vue2.0響應式的核心將在vue3.0 被Proxy取代。由於前者存在一些侷限,前者不能監聽到對象的屬性的增長和刪除,以及不能監聽到數組經過原生的方法對數組作的修改等問題,後者提供了對更多種類數據的攔截和對對象更好的支持。post
下一篇,寫寫Proxy的使用。性能
參考資料this
Vue 3.0 計劃spa