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