This is before I asked a question, asked hadn’t thought of before, when asked is a meng 😯 vue2 two-way data binding is to use the Object. The defineProperty, vue3 will use proxy data hijacking. So why does vue3 do this?
Vue data bidirectional binding principle
I’ve tried to describe this problem many times before, but I didn’t think it was clear enough. Vue is a bidirectional data binding using data hijacking combined with publish and subscribe mode. In the implementation of VUE, there are simply four parts:
- MVVM is used to initialize data
- The observer is used to add setters and getters to the initial data via Object.defineProperty, to add a subscription Object to the array when fetching data (call GET), to know when assigning data (call set). The notify of the publish subscription center is called to iterate through the subscription array of the current data, executing all of the watcher’s in it, and notifying the change update.
- Compiler is used to compile data into the DOM. There are three steps: 1. Move the real DOM into the fragment in memory. 2. Compile: Extract the desired element node V-model and text node {{}}; 3. Put the compiled fragment back on the page. The second step adds Watcher to the data compiled into the DOM, where the Watcher callback is notified to execute when the data changes.
- Watcher is the bridge between Oberver and Compiler.
The disadvantage of Object. DefineProperty
The first defect of object.defineProperty is that it cannot listen for array changes. But vUE can listen for array changes, so how does it do that? The following eight methods were used:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
Copy the code
Implementation example reference:
const aryMethods = ['push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse']; const arrayAugmentations = []; Arymethods.foreach ((method)=> {// Here is the prototype method of the native Arrayletoriginal = Array.prototype[method]; ArrayAugmentations [method] = {// arrayAugmentations[method] =function () {
console.log('I'm changed! '); // Call the corresponding native method and return the resultreturn original.apply(this, arguments);
};
});
let list = ['a'.'b'.'c']; __proto__ = arrayAugmentations; list.__proto__ = arrayAugmentations; list.__proto__ = arrayAugmentations; list.push('d'); // I am changed! 4 // Here the list2 prototype pointer has not been redefined, so it will output normallylet list2 = ['a'.'b'.'c'];
list2.push('d'); / / 4Copy the code
The above code reference: here
The second defect is that we can only hijack attributes of objects, so we need to traverse every attribute of each Object. If the attribute value is also an Object, then we need to traverse deeply, obviously hijacking a whole Object is a better choice.
Why is VUE3 using proxy?
1. Proxy can directly listen for array changes. 2. Proxy can listen on objects rather than properties. It puts a layer of “interception” in front of the target object, through which all external access to the object must pass, thus providing a mechanism for filtering and rewriting external access. A Proxy can simply hijack an entire object and return a new one.
conclusion
- Proxy returns a new Object. We can only manipulate the new Object to achieve our purpose. Object.defineproperty can only be modified by iterating through Object attributes.
- Proxy as the new standard will be subject to ongoing performance optimization by browser vendors, which is also known as the performance bonus of the new standard
- Of course, the disadvantage of Proxy is compatibility issues, and it can’t be implemented with Polyfill
Reference for this article: Resources 1