This is the sixth day of my participation in Gwen Challenge
One, foreword
The previous chapter mainly introduced how to realize data hijacking of array type in Vue data initialization process. The core ideas are as follows:
For performance reasons, Vue does not recursively hijack the array using Object.defineProperty. Instead, it intercepts and overwrites seven methods that can cause changes to the original array
At this point, the hijacking (deep hijacking) of reactive data (objects and arrays) is complete
This article continues to introduce the implementation of data broker on Vue instance in the process of Vue data initialization
Second, the realization of data proxy
1. How does Vue manipulate data
In Vue, it is possible to access and manipulate data externally directly through a VM instance:
let vm = new Vue({
el: '#app'.data() {
return { message: 'Hello Vue'.obj: { key: "val" }, arr: [1.2.3]}}});console.log(vm.message)
console.log(vm.arr.push(4))
Copy the code
Raises the question: how is vm.message equivalent to $options.data.message implemented?
2. How is the data currently being manipulated
Options, vm.options, vM. options, and vM. options.data
// src/state.js#initData
function initData(vm) {
let data = vm.$options.data;
data = isFunction(data) ? data.call(vm) : data;
observe(data);
data.message
data.arr.push(4);
}
Copy the code
To implement vm.message and $options.data.message equivalence
$options.data implements the data proxy
3. The idea of data proxy
To make the observed data available to external VM instances, mount the processed data directly to the VM
// src/state.js#initData
function initData(vm) {
let data = vm.$options.data;
data = vm._data = isFunction(data) ? data.call(vm) : data;
observe(data);
}
Copy the code
In this way, the VM instance can get data.message externally via vm._data.message
Next, broker the VM instance operation (vm.message) to vm._data
4. Implementation of data proxy
Hijacking data operations in _data via Object.defineProperty
That is, when vm.message is valued on the VM instance, it is proxyed to vm._data
// src/state.js#initData
function initData(vm) {
let data = vm.$options.data;
data = vm._data = isFunction(data) ? data.call(vm) : data;
observe(data);
// When vm.message is evaluated on the VM instance, it is proxyed to vm._data
for(let key in data){
Proxy(vm, key, '_data')}}// src/state.js#Proxy
/** * proxy method * When vm.key is fetched, proxy it to vm._data for *@param {*} Vm VM instance *@param {*} Key property name *@param {*} Source Proxy target, in this case vm._data */
function Proxy(vm, key, source) {
Object.defineProperty(vm, key, {
get(){
return vm[source][key]
},
set(newValue){ vm[source][key] = newValue; }})}Copy the code
5. Testing of data agents
let vm = new Vue({
el: '#app'.data() {
return { message: 'Hello Vue'.obj: { key: "val" }, arr: [1.2.3]}}});console.log(vm)
console.log(vm.message)
Copy the code
Observe the print result:
When obtaining a VM instance, all attributes of _data will be printed out on the current VM instance through the GET method, including all attributes of data and corresponding GET and set methodsCopy the code
Thus, the data broker is implemented:
When a value is taken from a VM instance, it is proxyed to the vm._data value
Three, the end
This paper mainly introduces the realization of data proxy on Vue instance in the process of Vue data initialization. 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
Next, debugging data hijacking and proxies