1, data response principle
1.1 what is MVVM? When the data changes, the View changes. When the data changes, the View changes. When the data changes, the View changes. View-model is a bridge between the template model and the View. Vue is non-intrusive. React and miniprograms are intrusive (they call pre-written apis when data changes).
this.a ++
this.setState({
a: this.state.a + 1
});
Copy the code
1.2. The central idea of data response? By overriding the get and set attribute methods of the data, let the data be rendered, all used by their subscribers, stored in their subscriber list; When the data changes, this method notifying all subscribers who have subscribed to it achieves the purpose of rerendering.
Official in-depth response schematic
Is that a little confusing? Never mind, simple chestnuts π° :
In Journey to the West, the monster (Watcher) is always thinking about (subscription) Tang Monk (Data), want to eat tang Monk (meat), sun Wukong (Component) after hearing (get) tang Monk caught news, to prepare to rescue (set). So came to the monster (Watcher) lair, with it a few rounds of war, successfully rescued Tang Monk (Data), to re-set foot (rendering) on the West (Vittual DOM Tree) purpose!
Object.defineproperty () method:
Data hijacking, data brokering, is described by MDN as: directly define a new property on an object, or modify an existing property on an object, and return the object.
Object.defineproperty (obj), 'a(define what property of this Object)', {value: 3}) var obj = {}; Object.defineproperty (obj, 'a', {get(){console.log(' access obj's a property! '); return 7; }, set(){console.log(' change a property of obj ', newValue); temp = newValue; } }) console.log(obj.a); obj.a = 9; console.log(obj.a);Copy the code
DefineReactive function: in order to solve the problem of defineProperty() method, get can not return the value just modified in set, and the value before modification will be displayed again. How to solve this problem? Define a global variable on the outside to change the value of the quantity.
DefineProperty (data, key,val){} var obj = {}; var temp; function defineProperty(data, key, val) { Object.defineProperty(data, key, { enumerable: true, configurable: True, get(){console.log(' access obj's '+ key +' property! '); return temp; }, set(){console.log(' change obj's '+ key +' property! ', newValue); if(val == newValue){ return; } temp = newValue; }}); } defineReactive(obj, 'a',10) console.log(obj.a); obj.a = 69; obj.a ++; console.log(obj.a);Copy the code
function defineReactive( target, key, value, enumerable ) { let that = this; if ( typeof value === 'object' && value ! = null && ! Array.isArray( value ) ) { reactify( value ); } Object.defineProperty( target, key, { configurable: true, enumerable: !! Enumerable, get () {console.log(' read the ${key} property '); return value; }, set (newVal) {console.log(' set the ${key} property to: ${newVal} '); value = reactify( newVal ); }}); }Copy the code
4. Reactive processing of arrays overwrite 7 properties: push, pop, shift, unshift, splice, sort, reverse;
const arrayPrototype = Array.prototype
const arrayMethods = Object.create(arrayPrototype);
const methodsNeedChange = [
'push','pop','shift','unshift','splice','sort','reverse'
];
methdsNeedChange.forEach(methodName => {
const original = arrayPrototype[methodName];
const ob = this.__obj__;
let inserted = [];
switch(methodName){
case 'push':
case 'unshift':
inserted = arguments;
break;
case 'splice':
inserted = arguments.slice(2);
brack;
}
if(inserted){
ob.obsetveArray(inserted);
}
def(arrayMethods, methodName, function(){
original.apply(this, arguments);
},false);
});
Copy the code
Interview question: How are responses implemented in arrays?
A: ArrayMethods = array.setPrototypeof (); arrayMethods = array.setprototypeof (); This makes it possible to invoke the newly rewritten seven methods.
5. What is dependence? The recursion that requires data is the dependency, collecting the dependency in the getter, firing the dependency in the setter; Collect dependent code and encapsulate it into a Dep class. Each instance of an Observer has an instance of Dep. Watcher is a mediator that notifies the component when data changes are relayed through Watcher.
Then take “journey to the West” said, the monster (Watcher) is how to know the Tang monk (Data) way here? It was discovered (collected), of course, by the elf (Dep- subscriber) sent out to patrol the mountain (depend); The goblin (Dep) patrol has three purposes (attributes) : The target, ID, and subs are captured when the Data passes through a pre-arranged hook, pushed to the top of the targetStack, and handed over to the Watcher.
6. When can I put Wather into Dep?
Dep class: encapsulates collected code and manages dependencies. Wather class: β Update property values; (newVal, oldVal) (newVal, oldVal)
Wather is set to the global location, and then read the data. In the getter function, it reads the wather that is reading from the global unique place, and it collects the wather back into the Dep.
export default class Dep{
constructor(){
this.subs = [];
}
addSub(sub){
this.shbs.push(sub);
}
dpend(){
if(Dep.target){
this.addSub(Dep.target);
}
}
notify(){
}
}
Copy the code
How to identify A.B.C in Vue? You take the higher-order function, and you take the values out layer by layer.
Loop through the target property flow chart
< script > deep dolls var / / o = {a: {b: {c: {d: 68}}}} var STR = 'A.B.C.D'; Function parsePath(STR){// according to. Var segments = str.split('.'); Return (obj) => {// for(let I = 0; i < segments.length; I++){// if obj exists if(! obj) return; Obj = obj[segments[I]]} return obj; Var fn = parsePath(STR); var v = fn(o); console.log(v); </script>Copy the code
Reference: www.infoq.cn/article/we3…
Juejin. Cn/post / 692191…
www.bilibili.com/video/BV1G5…