This is the 26th day of my participation in the August More Text Challenge

preface

The core feature of MVVM mode is two-way data binding. Vue builds a responsive system that can bind data in a declarative way, so as to automatically render views when data changes

The realization principle of Vue 2.x responsive system

Vue 2.x uses object.defineProperty () to add get() and set() methods to detect Object changes. Get () is called when the Object attribute value is obtained and set() is called when the Object attribute value is modified. You can then add code to the get() and set() methods to bind data to the view in both directions. A code example is as follows:

// Encapsulate the object.defineProperty () method
function defineReactive(obj, key, value){
  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newValue) {
       if(newValue ! == value) { updateView();// Trigger an update in the set() method
         value = newValue
       }
    }
}

// Detect changes in all attributes of an object
function observer(target){
  // If it is not an object data type, it is returned directly
  if(typeoftarget ! = ='object' ) {
    return target
  }  
  // Loop over all properties of the object and convert them to getter and setter forms
  for(let key in target){
    difineReactive(target, key, target[key])
  }
}

// Simulate the method of updating the view
function updateView() {
  console.log("View Update")}let user = {name: 'jack'}
// Detect all attribute changes in the user object
observer(user)
user.name = 'tom'
Copy the code

Run the above code and output:

View updateCopy the code

This code simply detects changes in an object’s properties and does not take into account the fact that the object properties themselves are objects (i.e., nested objects). Suppose the User object has an attribute, Address, which is itself an object. The code is as follows:

let user = {name: 'jack'.address: {city: 'Beijing'}
// Detect all attribute changes in the user object
observer(user)
user.address.city = 'hebei'
Copy the code

If you run the code above, you will see no output, indicating that the change to the Address object’s city property has not been detected. Therefore, you need to modify the code above by continuing to add get() and sett() methods for all properties of an object whose properties are also object types. It is also simple to implement by adding a recursive call to the observer() function in defineReactive(). A code example is as follows:

// Encapsulate the object.defineProperty () method
function defineReactive(obj, key, value){
  // Use recursive calls to detect nested properties of multiple objects
  observer(value)
  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newValue){
      if(newValue ! == value) {//observer(newValue)
         updateView(); // Trigger an update in the set() method
         value = newValue
       }
    } 
  })
}
Copy the code

Run the code again and you can see the output of the updated view