The difference between vue2 and vue3 bidirectional data binding

The new responsive mechanism adopts ProxyApi of ES6 and abandons object defineProperty()

Problems in Vue2 bidirectional data binding

About objects

Vue cannot detect the addition or removal of properties. Because Vue will perform getter/setter conversion on the property when initializing the instance, the property must exist on the data object for Vue to convert it into a responsive one

About arrays

Vue cannot detect changes in the following arrays:

When you use the index to set an array item directly, for example: VM items[indexOfItem] = newValue
When you modify the length of the array, for example: VM items. length = newLength

principle

Vue2.0 uses object Defineproperty object and hijacking + publish subscribe mode of object properties,
As long as the data changes, directly notify the change and drive the view update

<input type="text" id="in"/> The value entered is:<span id="out"></span>
var int = document.getElementById('in');
var out = document.getElementById('out');
// Define an object
const data={name:'peak',age:10}
// Traversing an object hijacks the properties of the object
Object.keys(data).forEach((key) => {
   Object.defineProperty(data, key, {
     // This attribute can only appear in the enumeration attribute of an object if and only if its enumerable is true
     enumerable: true,
     // When and only when the configurable of the attribute is true, the attribute descriptor can be changed and the attribute can be deleted from the corresponding object
     configurable: true, 
     get: ()=>{ // A method that provides getter s for attributes
       console.info(`get ${key}-${val}`)
       return val;
     },
     set: (newVal)=>{ // A method that provides a setter for a property
       // When the attribute value changes, we can do additional operations, such as calling the listener
       if(newVal === val ){ // If there is no change, do nothing else
        return;
       } 
       console.log(`Trigger view update function ${newVal}`);
       out.innerHTML = newVal;
     },
   });   
});
int.addEventListener('input', function(e) {
    obj.name = e.target.value;
})
data.age=25 // Trigger set method 

vue3 bidirectional data binding Proxy

The response formula in Vue3 adopts the Proxy method in ES6.

Proxy objects are used to define custom behaviors of basic operations (such as attribute lookup, assignment, enumeration, function call, etc.)

grammar

const p = new Proxy(target, handler)

The parameter target indicates the object to be wrapped by Proxy (it can be any type of object, including native array, function, or even another Proxy)

Parameter handler is an object that usually takes functions as attributes. The functions in each attribute define the behavior of processing p when performing various operations

let obj = {
    a: 1,
    b: 2
}
const proxy = new Proxy(obj, {
    get: function(target, prop, receiver) {
        return prop in target ? target[prop] : 0
    },
    set: function(target, prop, value, receiver) {
        target[prop] = 666
    }
})
console.log(proxy.a) // 1
console.log(proxy.c) // 0
proxy.a = 10
console.log(proxy.a) // 666
obj.b = 10
console.log(proxy.b) // Not 666, but 10 

In the above code, obj is the target object we want to proxy. The get and set methods are the two properties of the parameter handler, as follows:

handler.get() receives three parameters. The first parameter target is the target object of the proxy, the second parameter prop is the attribute of the target object of the proxy, and the third parameter is the proxy or the object inheriting the proxy, usually the proxy itself.

handler.set() receives four parameters, three of which are the same as the get method, except that one more value represents the new attribute value.

The above code indicates that when accessing the property of the proxy, intercept and judge whether the property is the property of the target object. If so, return its value, otherwise return 0.

When rewriting an attribute on the proxy, assign the rewritten attribute 666.

Note: the hijacking of data at this time only hijacks the proxy object proxy, which has nothing to do with the original object obj. Operating on obj will not be monitored.

Using proxy to realize a simple version of data response
<body>
    <h2 id="app"></h2>
  <input id="input" type="text" />
</body>
let app = document.getElementById('app')
let input = document.getElementById('input')

let obj = { // Source data
  text:'hello world'
}

let proxy = new Proxy(obj, {
  set: function(target, prop, value){ // The input event triggers hijacking and triggers the update method
    target[prop] = value
    update(value)
  }
})

function update(value){ // The update method is used to synchronize dom updates
    app.innerHTML = value
    input.value = value
}

input.addEventListener('input',function(e){ // Listen for changes in input data and modify the value of proxy
  proxy.text = e.target.value
})

proxy.text = obj.text // Initialize source data

Theory:

v2 adopts data hijacking combined with publisher subscriber mode through object Defineproperty() to hijack the setter of each property. The getter publishes a message to the subscriber when the data changes, and triggers the corresponding listening callback to render the view and realize the synchronization of data and view.
v3 uses the publisher subscription mode, combines the set and get methods of prosy in ES6 to hijack data, and further combines the update method of watchr

Keywords: Javascript Front-end Vue Vue.js Interview

Added by hsn on Mon, 07 Feb 2022 02:34:10 +0200