Let’s look at a simple example of the reactive form:

 var o = {};
    o.name = 'Joe';

    / / equivalent to the
    Object.defineProperty( o, 'age', {
        configurable: true.writable: true.enumerable:!true./ / can be enumerated
        value: 19});Object.defineProperty( o, 'gender', {
        configurable: true.enumerable: true./ / can be enumerated
        get () { 
            return 'Getter called';
        },
        set ( newVal ) {
            console.log( 'The new value assigned is:', newVal ); }});Copy the code

‘nan’ is not returned when it is evaluated.

If using both get and set requires an intermediate variable to store the real data, change it as follows:

var o = {};
    
    // Provide attributes to o
    o.name = 'Joe';

    / / equivalent to the
    Object.defineProperty( o, 'age', {
      configurable: true.writable: true.enumerable:!true./ / can be enumerated
      value: 19});// get and set
    // To be reactive means to do something along with an assignment or a read
    let _gender;
    Object.defineProperty( o, 'gender', {
      configurable: true.enumerable: true./ / can be enumerated
      get () { // If you use O.gender to access data, the get method (getter, reader) is called
        return _gender;
      },
      set ( newVal ) { // if o.gender = 'XXX ', the set method is called and the value is passed as an argument to the set
        // console.log(' assigned new value: ', newVal);_gender = newVal; }});Copy the code

This is the value assigned to _gender, but it is not safe to expose _gender to the global scope. Furthermore, setting get/set to a property requires setting an intermediate variable, which increases memory consumption.

How do you convert objects in Data to reactive in Vue?

How do I use a function closure like defineRective(Target, key, value, Enumerable) in Vue?

1. Here’s a simple version:

var o = {
      name: 'jim'.age: 19.gender: 'male'};// A simplified version
    function defineReactive( target, key, value, enumerable ) {
      // The inside of a function is a local scope, and the value is a variable used only within the function (closure).
      Object.defineProperty( target, key, {
        configurable: true.enumerable:!!!!! enumerable, get () {console.log( 'Read o's${key}Attribute ` ); / / additional
          return value;
        },
        set ( newVal ) {
          console.log( 'Set o's${key}Properties:${newVal}` ); / / additionalvalue = newVal; }})}// Convert the object to reactive
    let keys = Object.keys( o );
    for ( let i = 0; i < keys.length; i++ ) {
      defineReactive( o, keys[ i ], o[ keys[ i ] ], true );
    }
Copy the code

Console print result:

This is the simplified version, and you can see that the object is already responsive!

Data: {name: ‘zhang3 ‘}, but in real development, the object has N layers, the object has an array, how to convert the response type?

let data = {
      name: 'Joe'
      , age: 19
      , course: [{name: 'Chinese' },
        { name: 'mathematics' },
        { name: 'English'}]};// Queue can be used in addition to recursion (depth-first converted to breadth-first)



    let ARRAY_METHOD = [
      'push'.'pop'.'shift'.'unshift'.'reverse'.'sort'.'splice',];let array_methods = Object.create( Array.prototype );
    ARRAY_METHOD.forEach( method= > {
      array_methods[ method ] = function () {
        // Call the original method
        console.log( 'Call is intercepting' + method + 'methods' );

        // Make the data reactive
        for( let i = 0; i < arguments.length; i++ ) {
          reactify( arguments[ i ] );
        } 

        let res = Array.prototype[ method ].apply( this.arguments );
        // Array.prototype[ method ].call( this, ... arguments ); / / analogy
        returnres; }});function defineReactive( target, key, value, enumerable ) {
      // The inside of a function is a local scope, and the value is a variable used only within the function (closure).

      if ( typeof value === 'object'&& value ! =null&&!Array.isArray( value ) ) {
        // A non-array reference type
        reactify( value ); / / recursion
      }

      Object.defineProperty( target, key, {
        configurable: true.enumerable:!!!!! enumerable, get () {console.log( Read `${key}Attribute ` ); / / additional
          return value;
        },
        set ( newVal ) {
          console.log( ` set${key}Properties:${newVal}` ); / / additionalvalue = newVal; }}); }// Reactalize the object O
    function reactify( o ) {
      let keys = Object.keys( o );

      for ( let i = 0; i < keys.length; i++ ) {
        let key = keys[ i ]; / / the property name
        let value = o[ key ];
        if ( Array.isArray( value ) ) {
          / / array
          value.__proto__ = array_methods; // The array is reactive
          for ( let j = 0; j < value.length; j++ ) {
            reactify( value[ j ] ); / / recursion}}else {
          // Object or value type
          defineReactive( o, key, value, true );
        }
      }
    }
    

    reactify( data );
Copy the code