This is the 27th day of my participation in Gwen Challenge
preface
Vue3 has been released for a long time and we know that the biggest change to vue3 in this version is the change in the implementation of two-way binding, changing defineProperty to proxy. So why did Vue make this change? What are the advantages of proxy? Let’s talk about it today.
defineProperty
Es5 added defineProperty, which allows you to add or modify an attribute to an object and then return the object.
grammar
Object.defineProperty(obj, prop, descriptor)
obj
The target object
prop
Attribute name, usually a string, or symbol
descriptor
Attribute description of attribute name, object format
-
Value: Indicates the value of the attribute
-
Writable: Whether a property can be assigned. Default is false
-
Enumerable: Whether a property can be enumerable. The default is false
-
The default is false, and the default is different
-
The set setter function, called when a property is modified, cannot be used in conjunction with writable.
-
The get getter function is called when a property is accessed. It cannot be used together with value.
example
// Do getter/setter for name
let obj = Object.defineProperty({}, 'name', {
get () {
return 'the answer cp3'
},
set () {
console.log('Setter function called! ')}})console.log(obj.name) / / the answer cp3
obj.name = 'test' // The setter function is called!
Copy the code
As you can see, we’ve defined set and get to call GET when we get a property, and set when we set a property.
proxy
Es6 adds proxy to implement object proxy and intercept basic operations (add, delete, modify, and search).
grammar
new Proxy(target, handler)
target
The target object for which the proxy is needed
handler
Various operations on proxy objects, object forms, and keys are functions.
The following methods are supported:
get
Getter function This function is called when a property is accessedset
Setter functions call this function when a property is modifiedhas
This function is called when the in operator is usedgetPrototypeOf
Get the prototype chain, interceptObject.getPrototypeOf
setPrototypeOf
Set up prototype chain, interceptObject.setPrototypeOf
isExtensible
Determine whether an object can be extended and interceptedObject.isExtensible
preventExtensions
Set object unextensible, interceptObject.preventExtensions
getOwnPropertyDescriptor
Returns the property description of the property, interceptionObject.getOwnPropertyDescriptor
defineProperty
Define attributes, interceptObject.defineProperty
deleteProperty
Delete attributes, interceptdelete
The operatorownKeys
Returns an array of enumerable elements, interceptsObject.getOwnPropertyNames
andObject.getOwnPropertySymbols
apply
intercepttarget
It’s a function callconstruct
interceptnew
Operator, which requirestarget
It has to be a function.
These method names are the same as the method names of the Reflect object, and we can call Reflect directly from within.
example
// Basic usage
let obj = new Proxy({}, {
get () {
return 'the answer cp3'
},
set () {
console.log('Setter function called! ')}})// proxy {}
console.log(obj.name) / / the answer cp3
obj.name = 'test' // The setter function is called!
Copy the code
// Simulate private attributes
Use the has method to hide certain attributes from the IN operator
var handler = {
get (target, key) {
if (key.startsWith('_')) {
console.error('Access to private attributes is not supported! ')
return false
}
return Reflect.get(target, key)
},
set (target, key, val) {
if (key.startsWith('_')) {
console.error('Setting private properties is not supported! ')
return false
}
return Reflect.set(target, key, val)
},
has (target, key) {
if (key.startsWith('_')) {
console.error('Detecting private attributes is not supported! ')
return false
}
return Reflect.has(target, key)
}
};
var target = { _name: 'I'm a private property'.name: 'the answer cp3'};
var proxy = new Proxy(target, handler);
console.log('_name' in proxy); // false
proxy._name = 123; // false
console.log(proxy._name); // false
console.log('name' in proxy); // true
proxy.name = 123; // true
console.log(proxy.name); / / 123
Copy the code
The difference between
Here is the difference between the two in VUE:
-
DefineProperty can only listen for defined attributes, but cannot listen for new attributes or deleted attributes. Proxy listens for the whole object, and responds to new attributes or deleted attributes.
Here’s a simple code:
let name = 'the answer cp3' let obj = { name } for (let key in obj) { if (obj.hasOwnProperty(key)) { Object.defineProperty(obj, key, { get () { console.log('Get function called') return name }, set (val) { console.log('Set function called') name = val } }) } } obj.name = 'cp3' // The set function is called obj.age = 18 // No print set is called console.log(obj.name) // The get function is called console.log(obj.age) // No print Copy the code
As you can see, the new age attribute is not as successful as defineProperty, so vue can only provide a $set method to handle it.
For proxies, this problem is not present. Let’s see by example
let name = 'the answer cp3' let obj = new Proxy({ name }, { get (target, key) { console.log('Get function called') return target[key] }, set (target, key, val) { console.log('Set function called') target[key] = val } }) obj.name = 'cp3' // The set function is called obj.age = 18 // The set function is called console.log(obj.name) // The get function is called console.log(obj.age) // The get function is called Copy the code
-
Vue defineProperty does not implement array listening. It only provides push, POP, sort, reserve, splice, unshift, shift and other methods to trigger array listening. The proxy listens for the entire object and responds to new or deleted elements.
let arr = new Proxy([1.2.3], { get (target, key) { console.log('Get function called') return Reflect.get(target, key) }, set (target, key, val) { console.log('Set function called') return Reflect.set(target, key, val) } }) console.log(arr[0]) // The get function is called arr[3] = 4 // The set function is called arr.push(5)// The set function is called Copy the code
-
In addition, for defineProperty, there are only 2 GET and SET methods, while there are as many as 13 methods on proxy, which can basically meet various needs.
-
The problem with Proxy is that it is not compatible because it is a new API for ES6.
The last
Today, I will briefly talk about the comparison between VUe3 proxy and VUe2 defineProperty. Proxy can realize many more functions than defineProperty. I hope what I said today is helpful to you