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