It has been a year since the release of Vue3.0. It seems that the release of Vue3.0 will take some time. In the development plan, the following statement: Vue3.0 will transform the observer mode based on Proxy. Vue3.0 does not resort to ES5’s Object.defineProperty, but uses the latest Proxy syntax to implement Vue’s most fundamental reactive principle.



The following mainly describes the implementation of observer mechanism exploration from Object.defineProperty to proxy. At present, there are a lot of articles on the principle of deep responsiveness, many of which are well written. This article does not do deep source parsing in VUE. Just a shallow exploration and hand-write a simple Object. DefineProperty to implement the observer mechanism, and hand-write a simple Proxy to implement the observer mechanism, of course, the final release will be subject to the author. There are mainly the following points of knowledge to take you into

Object.defineproperty implements observer mechanism


2. Disadvantages of Object.defineProperty


3. Use proxy to realize simple observer mechanism


4, summarize

Object.defineproperty implements observer mechanism

Object defineProperty() method in ES5 and some basic knowledge, then write a simple response, and finally combine the vUE source code brief analysis.

1.1 Object-defineProperty Basic knowledge

Define Object.defineProperty() on developer.mozilla.org

Object.defineProperty()Method directly defines a new property on an object, or modifies an existing property of an object and returns the object

Object. DefineProperty (obj, prop, Descriptor) Parameter descriptions: 1. Obj Specifies the Object on which attributes are to be definedCopy the code


Here we focus on the third parameter in the syntax, the property descriptor: Descriptor

There are two main types of property descriptors that currently exist in objects: data descriptors and access descriptors. A data descriptor is a property with a value that may or may not be writable. Access descriptors are properties described by getter-setter function pairs. The descriptor must be one of these two forms; You can’t be both. The optional key, enumerable, value, WritableGet, and set parameters are configurable

1.2 Creating Objects

Usually we create objects to learn step by step about the use of key values in the object.defineProperty () method and property descriptors

[1] Normally we create an object as follows, then the console prints them we can see

      let vm = {
        name: 'the nuggets'
      }
      console.log(vm)Copy the code



[2] Next we create an Object via Object.defineProperty and set the property “name” for the Object to define or modify.

//    let vm = {
//      name: 'the nuggets'
//    }
    let vm = Object.defineProperty({},"name", {get() {
        console.log("Get");
        return "Nuggets"
      },
      set(newValue) {
        console.log("Set");
        console.log("New value:" + newValue);
      }
    })
 console.log(vm)Copy the code



In fact, both methods of creating an Object, the Object created through Object.defineProperty, we can see that with the two access descriptor key value methods like get and set, the Object becomes controllable to be observed, that is, hijacked. When we change or acquire properties of this object, we can control it.

Now we change vm.name = “juejin”, which we can see from the console

//    let vm = {
//      name: 'the nuggets'
//    }
    let vm = Object.defineProperty({},"name", {get() {
        console.log("Get");
        return "Nuggets"
      },
      set(newValue) {
        console.log("Set");
        console.log("New value:" + newValue);
      }
    })
vm.name = "juejin";
//console.log(vm)Copy the code




1.3 Implement observer mechanism, responsive object

let vm = {
  id:"juejin",
  name:"Nuggets"};
let keys = Object.keys(vm);
keys.forEach(key=>{
  let value = vm[key];
  Object.defineProperty(vm, key,{
     get() {
        console.log("Get");
        return value
     },
     set(newValue){
        console.log("Set");
        if(newValue! =value){ value = newValue; } } }) }) vm.id ="test";
console.log(vm)Copy the code



Each attribute is given get and set, so that the change of each attribute in the object will be monitored, that is, the responsive observer mechanism is realized.

1.4 VUE source code in the response principle brief analysis

The above example we try, array object detection is not work, then in vue array is how to implement the principle of reactive, we can see the vue source directory SRC/core/observer/index. The js, actually he is a judgment on the object, if is an array of objects, ObserveArray (), and you’ll notice there’s an arrayMethods, The ‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’, ‘sort’, and ‘reverse’ methods have been overwritten to not only do the same things, but also publish messages to subscribers. All other objects go to the walk () method.

1.5 Render data to the page

When we detect an object update, how do we synchronize the update to the page?

1. First, we need to find the node in scope (vue, which will have el:”#app”) where all page content will be rendered

2. Then go through any place on the node where the object is used, known as the interpolation of text with Mustache syntax, such as {{vm}}

3. Bind view updates


Object. DefineProperty

2.1 Cannot listen for the addition and deletion of non-existing attributes of objects

Vue only performs data hijacking on all the original attributes of the object. That is to say, Vue does not allow dynamic addition or deletion of the existing attributes of the object. It does not do data hijacking, so it cannot realize responsiveness.

For example,

<template>
  <div>
    <h1>{{ vm }}</h1>
    <button @click="addAttribute"</button> < button@click ="delAttribute"</button> </div> </template> <script>export default {
  data() {
    return { 
      vm:{
        id:"juejin",
        name:"Nuggets"
      }
    }
  },
  methods: {
    addAttribute() {
      this.vm.use = "codercao"
      console.log(this.vm)
    },
    delAttribute() {
      for(let k in this.vm) {
       if(k=='id'){
         delete this.vm[k]
       }
      }
      console.log(this.vm)
   }
  },
}
</script>Copy the code

Click On New Properties, and you’ll see that the VM printed by the console has the use property added, and the page has not changed in response

Click Delete Properties, and you’ll see that the VM printed by the console has removed the ID property, and the page has not changed in response



2.2 Array variation

Array objects can’t be controlled by properties or indexes such as length or index to be responsive, We can also see from 1.4 that the vue source code only rewrites the array ‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’, ‘sort’, ‘reverse’, but there is no way to implement the index control array responsivity.

2.3 Solutions to the above. Use the vue.set (object, propertyName, value) method

Modify the new attribute method in 2.1 above, and you will find that the page is responsive. The vue.set method describes the move

    addAttribute() {
     //this.vm.use = "codercao"
     this.$set(this.vm,'use'.'codercao')
      console.log(this.vm)
    },Copy the code


Three, the use of proxy to achieve a simple observer mechanism

3.1 Proxy Basic knowledge

ProxyObject to define the custom behavior of basic operations (such as property lookup, assignment, enumeration, function call, etc.)

grammarletp = new Proxy(target, handler); Parameter Description Target Proxy wrapped target object (which can be any type of object, including a native array, a function, or even another Proxy) Handler An object whose properties are functions that define the behavior of the Proxy when an operation is performedCopy the code


  let vm = {
      id:"juejin",
      name:"Nuggets"
    }
    let newVm = new Proxy(vm,{
      get(target,key){
        console.log("Get");
        return target[key];
       },
      set(target,key,newValue){
        console.log("Set");
        if(target[key]! ==newValue) target[key] = newValue; } }) newVm.use ="codercao"
    console.log(newVm)Copy the code

You’ll find that proxies also provide a simple observer mechanism, but if you dig deeper, you can also implement bidirectional binding.

Fourth, the end

This is the end of this article. As for how the author will use proxy to write the observer mechanism, we can see it when vue3.0 is released. This article mainly introduces you to explore the implementation of Object. This Object. DefineProperty defect and handling method, and then introduce proxy, is a relatively preliminary attempt, Vue has developed to now a few years, in fact, most people are already proficient in its application, pay attention to the source code and practice of Vue function principle, maybe there will be some improvement for each front-end people.