So let’s understand two points

1. Responsivity principle

2. Rely on collection

Response principle

Vue uses Object.defineProperty() to listen for attributes, so Internet Explorer 8 does not support this.

/ / have a vue object out new vue ({template: ` < div > < span > {{data1}} < / span > < / div > `, data: {data1: 'data1,}})Copy the code

Change the value of data1

This. data1 = 'I am modified'Copy the code

At this point, the datA1 property in vue does not listen for changes.

However, we can listen for changes to data1 via Object.defineProperty()

Enumerable: lets obj = new Vue(). Data,key = 'data1',val = obj[data1]; DefineProperty (obj,key,val,{enumerable:true, different :true, different :true, {return val; Set (newVal){if(val === newVal) return}})Copy the code

In this way, every time the value of data1 is changed, the data1 in vue can be changed accordingly

Depend on the collection

First of all, to know why there is such a thing as dependency collection, look at the following code, continue above

New vue ({template: `<div> <span>{{data1}}</span> </div>`, data:{ data1:'data1', Function defineReactive(obj,key,val){function defineReactive(obj,key,val){ DefineProperty (obj,key,{enumerable:true, 64x :true, different){return val; Set (newVal){if(val === newVal) return}})} // Data in vue has data1,data2, Let obj = new Vue().data object.keys (obj).foreach (key=>{this.definereative (obj,key,obj[key])})Copy the code

The problem is that we only use data1 in our template, and when we implement the implementation to listen for property changes, data2 is also being listened on, and we change the value of data2

This. data2 = 'change the value of data2'Copy the code

By adding listeners and modifying data2, the template will force a rendering even if data2 is not used, thus wasting resources

So we need to collect the properties that we need to listen to during template rendering, also known as dependency collection

First, we need a subscriber Dep class, and the properties being listened for are called watcher

Constructor (){this.constructor (){constructor(){this.subs = [] // addSub(sub){ This.subs.push (sub)} // Notify all watcher update views notify(){this.subs.foreach (watcher=>{// All observers subscribed to it should update watcher.update(); }}})Copy the code

And then we need an observer class

Constructor (){// Constructor (){/* When a new Watcher is created, Target = this // dep. target = this // dep. target is an instance of Watcher and assigns it to the global} update(){console.log(" View updated ~")}} Dep.target = nullCopy the code

Next, we start listening for properties

Function defineReative(obj,key,val){let Dep = new Dep() object.defineProperty (obj,key,{ Enumerable :true, different :true, get(){if(dep.target){// The new video works without any additional information. Dep.addsub (dep.target)// Add the current target to the subscriber to get the value. }, set(newVal){if(val === newVal) return dep.notify(); // Notify subscribers of changes}})}Copy the code

We have multiple properties that we need to traverse

Function observer(obj){object.keys (obj).foreach (key=>{this.definereative (obj,key,obj])})}Copy the code

The final step is to create a new Vue instance

Class Vue{constructor(options){this._data = options.data observer(this._data) // Create a responsive new Watcher(); Dependencies are collected only when the getter property is triggered when the template data is read. Console. log(' Simulating the rendering process ',this._data.text)}}Copy the code

When the observer() method is executed, the template is rendered back to execute the getter() method in the Dep to collect the dependency. When a property in data is modified, the setter() method is penalized. The same value is returned, and different values inform functions and templates that depend on the property to make corresponding changes.