It does several things: data hijacking, collecting dependencies, and distributing updates
1. Data hijacking: New Vue iterates through data objects, adding getters and setters to all attributes with Object.defineProperty
New Dep() relies on the collection class to trigger the getter for the data, which collects the current Watcher object
3. Update: When the setter is issued, the data dependent object (watcher object) is iterated and updated
The data was hijacked
Object attributes are hijacked to make the data observable with Object.defineProperty
class Vue { constructor(options) { observer(options.data); } observer(obj) { if (! obj || (typeof obj ! == 'object')) { return; } // walk through the data objects one by one with getter setters // 1. Keys (obj). ForEach (key => defineReactive(obj, key, obj[key])); } defineReactive(obj, key, val) { const dep = new Dep(); DefineProperty (obj, key, {enumerable: true, // The property enumerable is different: Get () {dep.addSub(dep.target); true // Attributes can be modified or deleted. Return val; }, set(newVal) { if (newVal === val) return; dep.notify(newVal); // send out updates}})}} You can see that the main function is the defineReactive function, which implements data hijacking using Object.definePropertyCopy the code
Rely on collecting & distributing updates
How does Vue know who to notify when data changes? It uses a subscriber Dep, which holds our observer object, notifies the observer when the data changes, and the observer completes the update by calling its own UPDATE method.
<! Constructor () {this.newdeps = []} addDep (watcher) {constructor () {this.newdeps = [] Update () {this.newdeps.foreach ((sub) => {sub.update(); this.newdeps.push (watcher); })}} <! Constructor () {constructor () {dep.target = this} update () {constructor () {constructor () {dep.target = this; Console. log(" View updated ~"); // Update view <! --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) --queueWatcher(this) This completes the collection of dependencies. Update notification dependencies when data changes.Copy the code
- Simple version of
Create (arrYuanXing) const keLongYuanXing = object.create (arrYuanXing) const keLongYuanXing = Object methodsArr = ['push', 'pop', 'shift', 'unshift', 'reverse', ForEach (method => {keLongYuanXing[method] = function()); {// Render UI renderView() // Method is a methodsArr item method name arrYuanXing[method]. Call (this,... }}) function renderView() {console.log('view changed '); } // 1. How do I know that obj.name has changed? // function observe(target) {// function observe(target) {// Function observe(target) Return if (Typeof Target! == 'object' || target == 'null') { return target } // 2. If (array.isarray (target)) {// Make the Array prototype point to the cloned prototype target.__proto__ = keLongYuanXing} // 3. For (const key in target) {// Let value = target[key] /* */ observe(value) /* vue 3.0 */ observe(value) /* vue 3.0 */ DefineProperty Object.defineProperty(target, key, {// assign get() {return value}, Set (newValue) {observe(value) renderView() value = newValue}})}} var Obj = {name: 'xiaoming ', arr: [1, 2, 3], sifangqian: {money: Observe (obj) observe(obj) // obj.name = 'China go!' // obj.sifangqian. Money = '9994' obj.arr.push(4) //! Object.defineproperty hijacking (do a few things before you change)Copy the code