preface

Vue3.0 was released on October 5, 2019. Now it is 2020, and it is estimated that the official version of Vue3.0 will come out soon.

It’s a big change from 2.0 to 3.0,

  • Structure: 2.0 with Flow,3.0 with TypeScript.
  • Performance: 3.0 optimized the algorithm of Virtual Dom.
  • Reactive principle: 2.0 use the Object defineProperty, 3.0 with the Proxy
  • .

Implementation principles of Vue2.0 and Vue3.0

  1. Vue 2.0

    The principle of Vue2.0 implementation of MVVM(two-way data binding) is to hijack the setter and getter of each attribute through object.defineproperty, publish the message to the subscriber when the data changes, and trigger the corresponding listening callback.

    Vue’s official website also explains:

  2. Vue 3.0 is responsive based on ES6: Proxy

The differences between Vue2.0 and Vue3.0 are as follows:

Vue2.0

  • Based on Object.defineProperty, there is no ability to listen on the array, so you need to redefine the array prototype to achieve responsiveness.
  • Object.defineproperty cannot detect the addition and deletion of Object attributes.
  • Since Vue performs getter/setter conversions on properties when initializing instances, all properties must exist on the data object for Vue to convert it to responsive.
  • Deep monitoring requires one-time recursion, which has a large impact on performance.

Vue3.0

  • With Proxy and Reflect, you can listen natively on arrays, listening for object attributes to be added and removed.
  • You can significantly improve performance by not having to iterate through data’s properties at once.
  • Because Proxy is a new attribute in ES6, some browsers do not support it and can only be compatible with IE11.

Vue2. X implements responsiveness

Here is a step-by-step implementation of the simple version of Vue2.0 based on Object.defineProperty.

  1. Because Object.defineProperty cannot listen on an array, the array type implements responsiveness and needs to be handled. If it is an array type, override the array prototype method (‘push’,’pop’,’shift’,unshift)

    Const oldArrayProperty = array.prototype; const arrProto = Object.create(oldArrayProperty); ["push","pop","shift","unshift","splice"].forEach( methodName => (arrProto[methodName] = function() { updateView(); oldArrayProperty[methodName].call(this, ... arguments); }))Copy the code
  2. The passed data property is deeply listened to determine whether it is an object or an array.

    function observer(target){ if(typeof target ! = = 'object' | | target = = = null) {return target} / / if it is an array type, rewrite array prototype method (" push ", "pop", "shift" and "unshift", "splice") if(Array.isArray(target)){ target.__proto__ == arrProto; } // If it is an object, iterate over all the properties of the object, DefineProperty (let key in target){defineReactive(target,key,target[key])}}Copy the code
  3. The core API Object.defineProperty converts an incoming property into a getter/setter

    Function defineReactive(target, key, value){// If the object has more layers, call the Observer listener method again for deeper listening. observer(value); Object.defineProperty(target, key, { get(){ return value; }, set(newValue){// Observer (value); if(newValue ! == value){ value = newValue; // Data drives the view. If the data changes, the view update method is called. The corresponding Vue is VDOM updateView(); }}})}Copy the code
  4. Data updates trigger view updates, which is how MVVM bindings work, which involves compiling Vue templates into render functions, performing Virtual Dom, Diff algorithms, vNodes, etc.

    Function updateView(){console.log(' updateView ')}Copy the code

5. Use

Const data = {name: "zhangsan", age: 20, info: {address: "Zhangsan" // nums: [10, 20, 30]}; observer(data);Copy the code

Vue3.0 is responsive

Vue3.0 is based on Proxy to do data hijacking Proxy. It can support the response of array natively, without rewriting the prototype of array, and can directly support the addition and deletion of attributes, which is clearer than Object. DefineProperty of Vue2.

  1. Core code (very little)

    const proxyData = new Proxy(data, Const ownKeys = reflect.ownkeys (target) if(ownkeys.includes (key)){get(target,key,receive){// Handle only its own (non-prototype) attributes const ownKeys = reflect.ownkeys (target) if(ownkeys.includes (key)){ Console. log('get',key) // listener} const result = reflect. get(target,key,receive) return result}, set(target, key, val) Reveive){// Duplicate data, Const oldVal = target[key] if(val == oldVal){return true} const result = reflect. set(target, key, Val,reveive) return result}, // deleteProperty(target, key){ const result = Reflect.deleteProperty(target,key) return result } })Copy the code
  2. use

    Const data = {name: "zhangsan", age: 20, info: {address: "Zhangsan" // nums: [10, 20, 30]};Copy the code

    Proxy will directly listen to the content of data. It is very simple and convenient. The only disadvantage is that some browsers cannot be compatible with Proxy or hack, so it can only be compatible with IE11 at present.

All the source code

You can copy the code directly to the Chrome console for debugging and printing.Copy the code
  1. Vue2.0

    Function defineReactive(target, key, value) {// Observer (value); Object.defineProperty(target, key, { get() { return value; }, set(newValue) {// Deep listener observer(value); if (newValue ! == value) { value = newValue; updateView(); }}}); } function observer(target) { if (typeof target ! == "object" || target === null) { return target; } if (Array.isArray(target)) { target.__proto__ = arrProto; } for (let key in target) { defineReactive(target, key, target[key]); Const oldAddrayProperty = array.prototype; const arrProto = Object.create(oldAddrayProperty); ["push", "pop", "shift", "unshift", "spluce"].forEach( methodName => (arrProto[methodName] = function() { updateView(); oldAddrayProperty[methodName].call(this, ... arguments); })); Function updateView() {console.log(" updateView "); } const data = {name: "zhangsan", age: 20, info: {address: "Beijing" // nums: [10, 20, 30]}; // Execute a responsive observer(data);Copy the code
  2. Vue3.0

    const proxyData = new Proxy(data, Const ownKeys = reflect.ownkeys (target) if(ownkeys.includes (key)){get(target,key,receive){// Handle only its own (non-prototype) attributes const ownKeys = reflect.ownkeys (target) if(ownkeys.includes (key)){ Console. log('get',key) // listener} const result = reflect. get(target,key,receive) return result}, set(target, key, val) Reveive){// Duplicate data, Const oldVal = target[key] if(val == oldVal){return true} const result = reflect. set(target, key, val,reveive) console.log('set', key, val) return result }, deleteProperty(target, key){ const result = Reflect.deleteProperty(target,key) console.log('delete property', Key) console.log('result',result) return result}}) const data = {name: "zhangsan", age: 20, info: {address: "Beijing" // need deep listener}, nums: [10, 20, 30]};Copy the code