This is the 7th day of my participation in Gwen Challenge
One, foreword
In the previous part, the realization of data proxy on Vue instance in the process of Vue data initialization was introduced. The core ideas are as follows:
- Expose data on the vm._data instance property
- Delegate the vm. XXX operation to vm._data using Object.defineProperty
In this paper, the current version of data hijacking and instance value proxy breakpoint debugging and process combing
Two, data hijacking
1. Debug the Demo
let vm = new Vue({
el: '#app'.data() {
return {
message: 'Hello Vue'./ / value
obj: { key: "val" }, // Nested objects
arr: [1.2.3]} / / array}}); vm.message// Access properties
vm.arr.push(4) // Manipulate arrays
Copy the code
Ready to start breakpoint debugging:
Vue initialization entry
The Vue constructor, passing in the external options option, calls the prototype method _init to start the Vue initialization process
3. InitMixin method
Mount the _init method on the Vue prototype, taking the options option passed in when the Vue is initialized
The initMixin method does the following:
- Initialization of data (multiple types of data: Data, props, Watch, computed…)
- Once the data is initialized, render the data to the page
The vm $options:
- $options = Vue; $options = Vue; $options = Vue;
- Make methods in Vue easily accessible to options via the instance’s $options variable
- Put options on the $options variable. Properties in options do not contaminate the VM instance
4. InitState method
InitState method: initializes state (in this case, state is data, which can come from multiple sources)
Currently, only data is processed. If options.data exists, go to initData to initialize data
5. InitData method
InitData method: initializes data
$options.data (Vue); $options.data (Vue);
Data can be a function or an object:
- When data is a function: Call data to get the return value of the function – object, as the current instance data source data
- When data is not a function: Data must be an object that serves directly as the instance data source
After this step of processing, data is processed as an object type for use by subsequent processes
Data = vm._data
- The external instance VM cannot directly access the internal data attribute of the initData method.
- In order to enable the external instance VM to access the data attribute directly, the _data instance attribute is added to the VM instance, that is, data = vm._data;
- Data is an object, that is, a reference type, so data shares a reference with vm._data
6, Observe method (Observe entrance)
Observe Method: Data observation entry
After the observe is invoked, data is observed. Data is the responsive data
Data observation is deeply recursive. Observe is the entry point for data observation.
So, this is the first time the observe method is called, and value is the entire data root object;
- If the value is not an object, the current processing is finished (in subsequent recursions, it means that the processing of this layer is finished and back to the previous layer);
- If value is an object, create the data as an Observer instance; (The first call to observe creates the data root object as an Observer instance.)
7, with the Observer
In the constructor of the Observer class, the two cases where value is an array and an object are handled separately
Data hijacking – Object type:
- Walk method: iterates through object attributes, calling defineReactive method for each attribute;
- DefineReactive method: Add get and set methods to attributes via Object.defineProperty for data hijacking
Data hijacking – Array types:
- Rewrite 7 prototype methods that change array data (e.g., splice, push, unshift)
- The first time you enter Observer: value is the root data (which must be the object type), call the Walk method
8. Walk method
Walk: iterates through all (enumerable) attributes on the object, executing defineReactive in turn for data hijacking;
In the loop, add data hijacking for each of the three attributes in turn by calling defineReactive
The message:
Obj:
Arr:
DefineReactive method
DefineReactive is an external walk method for object attribute traversal, recursive call for each attribute; DefineReactive method: Creates Object. DefineProperty recursively for each attribute, which is a depth-first process
Deep observation data.message
Enter defineReactive method for the first time:
Obj = data root object, key = “messge”, value = string “Hello Vue”
Observe method first, perform deep recursive processing (depth first)
In the observe method, since the value of message is the string ‘Hello Vue’ and is not an object,
So instead of recursing down the path, return handles the Message property in data
In the defineReactive method:
Object.defineproperty on obj Object (first entry, obj is the root Object data)
Redefine the message property with the values GET and set
At this point, message processing is complete
Deep observation data.obJ
The second time, enter the defineReactive method:
{key: “val”}
Observe method first, perform deep recursive processing (depth first)
Since value is an object type {key: “val”}, the underlying layer needs to be handled recursively.
So, create value as an Observer instance
Within the Observer constructor, the object processing logic is performed, traversing all of the object’s properties through the Walk method
Continue to call the defineReactive method for each attribute and continue to do deep recursive observations
The walk method iterates through all the attributes of the data argument (value object {key: “val”}) and calls defineReactive to process the next layer:
The defineReactive method is called the first time:
Obj = object {key: “val”}, key = “key” value = “val”
In the observe method, since the key is the string ‘val’ and is not an object,
So, instead of recursing down, return handles the “key” property of the {key: “val”} object
Is the “key” attribute in the Object {key: “val”}, through object.defineProperty, to achieve the observation of the key attribute
{key: “val”} {key: “val”} {key: “val”} {key: “val”} {key: “val”
After executing the observe method, {key: “val”} deep observation of the internal properties of the object is complete
To continue the observation except for the {key: “val”} object, then the defineReactive method:
{key: “val”}
This completes the processing of obj
Deep observation data.arR
Third time, enter the defineReactive method:
Obj = data root object, key = “arr”, value = array [1,2,3]
Observe method first, perform deep recursive processing (depth first)
Since value is an array {key: “val”} (object type), the underlying layer needs to be processed recursively,
So, create value as an Observer instance
Value is an array type, we need to rewrite some of the array prototype methods:
Overriding the following seven methods is equivalent to intercepting an array update
Observe internally overwrites the array prototype method
The arR attribute of data is then processed with Object.defineProperty
In this way, the processing of ARR is completed, that is, the processing of the whole data is completed, and the observation of the data is completed
Complete data observation
The inner layer:
- Array type: does not listen on every item of the array, only overwrites the array part of the prototype method;
- Object type: Makes a deep observation of the properties of the object
Note: Since in recursive processing, objects will be deeply processed, so if there are objects in the array, the deep observation is also implemented;Copy the code
Third, data broker
1. Implement data proxy
To allow direct manipulation of the data on the instance, all attributes of the object are brokered once
Value proxy of VM instances: Proxy all vm. XXX value operations to vm._data. XXX
Proxy for three attributes in data:
1) Proxy message:
2) Agent OBJ:
3) Agent ARR
Implementation principle:
Add a layer of proxy for values and updates to vm._data using Object.defineProperty
2. The example value is vm.message
Because the proxy method proxies vm. XXX to vm._data.xxx via Object.defineProperty
So, when a value operation is performed through vm. XXX, the get method is entered and will be proxied to vm._data.xxx
Vm. _data. XXX triggers the get method on vm._data
Vm. message is proxied to vm[_data][message] for value, and the original message attribute is fetched through such a layer of proxiing.Copy the code
3. Array operation vm.arr.push
This will start with the vm.arr value operation, as above:
Because the proxy method proxies vm. XXX to vm._data.xxx via Object.defineProperty
Therefore, when a value operation is performed through vm. XXX, the get method is entered and is proxied to vm._data. XXX
[‘_data’].[‘arr’]
Vm.[‘_data’].[‘arr’] triggers the get method of vm._data
After fetching the arR array, call.push to manipulate the array:
At this point, we enter the array override push method:
Fourth, the current version of the problem analysis
1. Deep observation logic
The current version of the source code, to achieve the logic of deep observation is as follows:
- Make a deep observation of the data root object
- Properties inside data are observed recursively if they are objects
- If the property inside data is an array, it overrides the methods on the array’s prototype chain (7)
2. Supported data observations
The current version supports the following data observations:
- Data root objects (objects and nested objects implement deep observations)
- Values in data (add get, set methods for attributes in objects)
- Data in the array (rewrite the array prototype method, currently does not do recursive processing, only the realization of the array of single-layer hijacking)
- Objects in data (objects and nested objects for deep observation)
- The object of the object in data… (Objects and nested objects enable deep observation)
- The value of the object in data (object and nested object deep observation, while adding get and set methods for the attributes in the object)
3. Unsupported data observations
The current version does not support the following data observations:
- Data in the array of objects (rewrite the array prototype method, currently does not do recursive processing, only the realization of the array of single-layer hijacking)
- Data in the array of the array in the array (rewrite the array prototype method, currently does not do recursive processing, only the realization of the array of single-layer hijacking)
- New objects are not observed
- The newly added array is not observed
4. Mechanism of Vue2 2.x
- Changing the array subscript and length does not trigger an update (only overrides the array part of the prototype method); $set = vm.$set
- The new attribute cannot be observed, and the update will not be triggered. $set = vm.$set
Four, the end
This article through Vue Demo breakpoint debugging, the current version of data hijacking and data proxy process combing
At the same time, compared with the functions provided by Vue2. X, the problems and shortcomings of the current version of data observation are analyzed
Next, a deeper look at arrays