preface

The responsive realization of Vue is an important part of Vue principle, and the correct understanding of the responsive form of Vue is more conducive to our understanding and use of Vue.

This article will talk about how Vue3 implements responsiveness. Previously, Vue2 mainly relies on THE ES5 Object.defineProperty API to implement responsiveness. We use this API to make objects observable, combined with dependency collection to implement responsiveness system. For details, please refer to the following video: How to write Vue

A,Object.definePropertyThe disadvantages of the

  • Deep listening requires one-time recursion (affects performance)

  • Unable to listen for new attributes/delete attributes (Vue. Set, Vue. Delete)

  • Unable to native listen array, requires special handling

Vue3 addresses these issues by using ES6 proxies and Reflect to implement responsiveness. Vue3 uses ES6 syntax, which is the stuff of modern JavaScript and doesn’t support IE, so give up IE and download Chrome!!

Second,Vue3Responsive implementation

2.1 understandES6 Reflect

Suppose we now have a commodity with price and quantity attributes.

let product = { price: 5.quantity: 2 }
Copy the code

Now we have three ways to print the properties of an object:

  1. First, we can use the typical “dot” notation
console.log('quantity is ' + product.quantity)
Copy the code
  1. We can also write it in parentheses
console.log('quantity is ' + product['quantity'])
Copy the code
  1. And then finally we can use itES6 ReflectAs you can see.
console.log('quantity is '+ Reflect.get(product, 'quantity')).
Copy the code

As you can see, all three work, but Reflect has a super power πŸ€·β™€οΈ that I’ll show you after we understand Proxy.

2.2 understandES6 Proxy

Proxy is a placeholder for another object that is delegated by default.

If I create a proxiedProduct and declare a Proxy, and THEN I call ProxiedProduct.quantity, it will:

  1. It calls firstProxy
  2. thisProxyCall the product again
  3. And then go back toProxy
  4. Returns the product to the console log
  5. It will print out at the end2
let product = { price: 5.quantity: 2 }

let proxiedProduct = new Proxy(product, {})

console.log(proxiedProduct.quantity)
Copy the code

Basically, it’s an object delegate. The second parameter in Proxy is called a handler, and in this handler you can pass a trap that lets you intercept basic operations such as property look-ups, or enumerations, or function calls. Next we will try to implement the intercept get operation.

2.3 the use ofProxyTry to intercept the GET operation

let product = { price: 5.quantity: 2 }

let proxiedProduct = new Proxy(product, {
    get(){
        console.log('Get was called')
        return 'Not the value'}})Copy the code

In this example, when we call GET in proxiedProduct, we want to change the behavior of get. Now when it is called, let’s simply do the output. Let’s look at the result:

Okay, so now we’ve implemented, when we get the property value, we’ve implemented our owngetMethod, but the current get method is completely useless, so let’s return the value honestly ~

2.4 the use ofProxyIntercepting the correct posture of the GET operation

let product = { price: 5.quantity: 2 }

let proxiedProduct = new Proxy(product, {
    get(target, key){
        console.log('Get was called with key= '+ key)
        return target[key]
    }
})
console.log(proxiedProduct.quantity)
Copy the code

We declare two arguments to get, and then we print ‘get was called with key= key’, and we’re going to use the notation in parentheses to return the value of the key property, so when we call conosle.log, It will call our proxiedProduct via get(target), in this case the parameter target is the product we passed, our key is quantity, because we want quantity, and it will print out correctly, let’s look at the result:

We mentioned earlier that Reflect can be very useful, so let’s try using Reflect in a Proxy.

2.5 inProxyIn the use ofReflect

let product = { price: 5.quantity: 2 }

let proxiedProduct = new Proxy(product, {
    get(target, key, receiver){
        console.log('Get was called with key= '+ key)
        // return target[key]
        return Reflect.get(target,key,receiver)
    }
})
console.log(proxiedProduct.quantity)
Copy the code

We will now have an additional parameter, called receiver, which will be passed to our Reflect call. This ensures that when our object has a value or function that inherits from another object, the this pointer will correctly point to the object in use. This will avoid some of the reactive warnings we had in Vue2, and the printout will of course remain the same:

We also need to use Proxy to intercept the set method, which we’ll implement next

2.6 the use ofProxyIntercept set operation

let product = { price: 5.quantity: 2 }

let proxiedProduct = new Proxy(product, {
    get(target, key, receiver) {
        console.log('Get was called with key= '+ key)
        return Reflect.get(target,key,receiver)
    },
    set(target, key, value, receiver) {
        console.log('Set was called with key = ' + key + 'and value = ' + value)
        return Reflect.set(target, key, value, receiver)
    }
})
proxiedProduct.quantity = 100
console.log(proxiedProduct.quantity)
Copy the code

Our set method receives the target, the key and the value, the receiver four parameters, we will be in the set is invoked, print out our key and the value, then we Reflect the call. The set, represents the parameters of target, the key and the value, the receiver, Let’s change the quantity of quantity to test it:

So we have successfully intercepted set. Remember I said that the second argument to Proxy is called a handler? We can now wrap this part of the handler to make it look more like Vue3’s source code

2.7 Encapsulate the handler function to make it more like Vue3 source code

function reactive(target){
    const handler = {
        get(target, key, receiver) {
            console.log('Get was called with key= '+ key)
            return Reflect.get(target,key,receiver)
        },
        set(target, key, value, receiver) {
            console.log('Set was called with key = ' + key + 'and value = ' + value)
            return Reflect.set(target, key, value, receiver)
        }
    }
    return new Proxy(target, handler)
}
let product = reactive({ price: 5.quantity: 2 })
product.quantity = 4
console.log(product.quantity)
Copy the code

We created a function called Reactive, which you’ll be familiar with if you’ve used the Composition API, and we encapsulated our get and set methods into a constant handler, and then we created a new Proxy that passed our target and our handler, Now when we declare a product, we just need to pass an object to Reactive, and reactive will return a Proxy, which we will use as a raw object, we change the value of Quantity, and the console prints the value of Quantity, When we execute this code, we get what we expect:

The last

⚽ read this, I believe you have a deeper understanding of Vue3’s responsive implementation, although Vue3 still has some browser compatibility problems, but I think soon, IE will be eliminated, Vue3 will replace Vue2, so we need to learn more actively Vue3 use and principle, Later I will also update the Vue3 principle of other articles ~ ⚾ if you are interested in this article welcome to praise attention + collection, more wonderful knowledge is waiting for you! 😘 πŸ€GitHub blogs at github.com/Awu1227. πŸ‰ I have other columns, please read ~ 🏐 play the beauty of CSS 🎱Vue from giving up to getting started 🎳 simple JavaScript