/* */ var arrayKeys = Object.getOwnPropertyNames(arrayMethods);//獲取arrayMethods的屬性名稱 /** * By default, when a reactive property is set, the new value is//默認情況下,當一個響應的屬性被設置,新的值也轉換成響應的。然而當經過向下支撐時,我們不想促使轉換,因為這值也許是一個嵌套值在一個凍結的數據結構,轉換它時將會失去最優化 * also converted to become reactive. However when passing down props, * we don't want to force conversion because the value may be a nested value * under a frozen data structure. Converting it would defeat the optimization. */ var observerState = { shouldConvert: true, isSettingProps: false }; /** * Observer class that are attached to each observed//觀察者類被綁定到每一個觀察對象,一旦綁定,這個觀察者使目標對象的屬性鍵轉換到getter/setter方法,收集依賴和發送的更新 * object. Once attached, the observer converts target * object's property keys into getter/setters that * collect dependencies and dispatches updates. */
接下來是最關鍵的一部分
var Observer = function Observer (value) { this.value = value; this.dep = new Dep(); this.vmCount = 0; def(value, '__ob__', this);//給value定義一個‘——ob——’屬性,屬性的值為這個Observer對象 if (Array.isArray(value)) {//判斷是不是一個數組 var augment = hasProto ? protoAugment : copyAugment; augment(value, arrayMethods, arrayKeys); this.observeArray(value); } else { this.walk(value); } }; /** * Walk through each property and convert them into//walk方法穿過每一個屬性並且把他們轉換到getter或者setter方法。這個方法應當僅在value的類型為對象時候調用 * getter/setters. This method should only be called when * value type is Object. */ Observer.prototype.walk = function walk (obj) { var keys = Object.keys(obj);//獲取對象的每個鍵 for (var i = 0; i < keys.length; i++) { defineReactive$$1(obj, keys[i], obj[keys[i]]); } }; /** * Observe a list of Array items.//觀察一個數組項目的列表 */ Observer.prototype.observeArray = function observeArray (items) { for (var i = 0, l = items.length; i < l; i++) { observe(items[i]); } }; // helpers /** * Augment an target Object or Array by intercepting//增加一個目標對象或者數組通過用__proto__截取原型鏈 * the prototype chain using __proto__ */ function protoAugment (target, src) { /* eslint-disable no-proto */ target.__proto__ = src; /* eslint-enable no-proto */ } /** * Augment an target Object or Array by defining * hidden properties.//增大一個目標對象或者數組通過定義隱藏的屬性 */ /* istanbul ignore next */ function copyAugment (target, src, keys) { for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; def(target, key, src[key]); } } /** * Attempt to create an observer instance for a value,//嘗試創建一個觀察者實例化一個值 * returns the new observer if successfully observed,//返回一個新的觀察者如果成功被觀察 * or the existing observer if the value already has one.//如果值已經有一個了則返回存在的觀察者 */ function observe (value, asRootData) { if (!isObject(value)) {//如果value不是對象,那么就到此結束 return } var ob; if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__; } else if ( observerState.shouldConvert && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { ob = new Observer(value); } if (asRootData && ob) { ob.vmCount++; } return ob } /** * Define a reactive property on an Object.//定義一個響應的屬性在一個對象上 */ function defineReactive$$1 ( obj, key, val, customSetter ) { var dep = new Dep(); var property = Object.getOwnPropertyDescriptor(obj, key); if (property && property.configurable === false) { return } // cater for pre-defined getter/setters//滿足預定義的 getter/setters var getter = property && property.get; var setter = property && property.set; var childOb = observe(val); Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { var value = getter ? getter.call(obj) : val; if (Dep.target) { dep.depend(); if (childOb) { childOb.dep.depend(); } if (Array.isArray(value)) { dependArray(value); } } return value }, set: function reactiveSetter (newVal) { var value = getter ? getter.call(obj) : val; /* eslint-disable no-self-compare */ if (newVal === value || (newVal !== newVal && value !== value)) { return } /* eslint-enable no-self-compare */ if ("development" !== 'production' && customSetter) { customSetter(); } if (setter) { setter.call(obj, newVal); } else { val = newVal; } childOb = observe(newVal); dep.notify(); } }); } /** * Set a property on an object. Adds the new property and * triggers change notification if the property doesn't * already exist. */ function set (obj, key, val) { if (Array.isArray(obj)) { obj.length = Math.max(obj.length, key); obj.splice(key, 1, val); return val } if (hasOwn(obj, key)) { obj[key] = val; return } var ob = obj.__ob__; if (obj._isVue || (ob && ob.vmCount)) { "development" !== 'production' && warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.' ); return } if (!ob) { obj[key] = val; return } defineReactive$$1(ob.value, key, val); ob.dep.notify(); return val } /** * Delete a property and trigger change if necessary. */ function del (obj, key) { if (Array.isArray(obj)) { obj.splice(key, 1); return } var ob = obj.__ob__; if (obj._isVue || (ob && ob.vmCount)) { "development" !== 'production' && warn( 'Avoid deleting properties on a Vue instance or its root $data ' + '- just set it to null.' ); return } if (!hasOwn(obj, key)) { return } delete obj[key]; if (!ob) { return } ob.dep.notify(); } /** * Collect dependencies on array elements when the array is touched, since * we cannot intercept array element access like property getters. */ function dependArray (value) { for (var e = (void 0), i = 0, l = value.length; i < l; i++) { e = value[i]; e && e.__ob__ && e.__ob__.dep.depend(); if (Array.isArray(e)) { dependArray(e); } } }