Example of handwritten Vue 2.0 data hijacking

  • 2021-11-01 02:08:36
  • OfStack

Directory 1: Build webpack 2: Data hijacking 3: Summary

1: Build webpack

Simply build the configuration of webpack under 1. Create a new folder, and then under init1. Then create a new webpack. config. js file, which is the configuration file for webpack. Install simple dependencies under 1.


npm install webpack webpack-cli webpack-dev-server -D

Create a new public/index. html and src/index. js in the same level directory as the export file and the entry file.

j Simple Configuration 1 webpack, in webpack. config. js file:


const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
 entry: './src/index.js',
 output: {
  filename: 'bundle.js',
  path: path.resolve(__dirname, 'dist')
 },
 resolve: { 
  modules: [
  path.resolve(__dirname, ''), path.resolve(__dirname, 'node_modules')  
  ] 
 },
 plugins: [  
  new HtmlWebpackPlugin({   
   template: path.resolve(__dirname, 'public/index.html')  
  }) 
 ]
}

ok, basic configuration of webpack can get down to business.

2: Data hijacking

In v2, vue is instantiated by new Vue (el, options). We need to create a new vue file, the method of data hijacking 1 into vue.

Create a new vue/index. js as the entry file for data hijacking.


import {initState} from './init.js';

function Vue (options) {
 this._init(options);  //  Data initialization 
}
Vue.prototype._init = function (options) {
 var vm = options; //  Save 1 The following example 
 vm.$options = options; //  Instance mount 
 initState(vm);   //  Instance initialization 
}

Create 1 new init. js file initialization instance:

Pay attention to several problems during initialization:

1. computed, watch and data need to be treated respectively.

2. Do not modify directly on the user-defined data.

3. The official designation of data as a function is to ensure that there is no pollution in the internal scope of the component. It is impossible to access the data function directly, and it needs to be executed automatically. data can also be an object (which needs to be considered)

4. data is fetched in this way through vm._data. xxx, but data is not required in vue, so overrides need to be intercepted here.

5. Internal reference types require recursion


function initState (vm) {
 var options = vm.$options; //  Get options
 if (options.data) {
  initData(vm); //  Because computed , watch All need to be initialized here, so for the data Initialization 
};

function initData (vm) {
 var data = vm.$options.data; //  Right data Re-assign, do not change the user-defined data
 data = vm._data = typeof data === 'function' ? data.call(vm) : data || {};
 for (var key in data) {
  proxyData(vm, '_data', key);   //  Right data Re-assignment of the value of 
 };
 observe(vm._data); //  Right data Observe internally 
}

Create a new proxy. js as the proxy layer:


function proxyData(vm, target, key) { 
 Object.defineProperty(vm, key, {  
   get () {   
   //  Interceptions were made here:  vm.xxx => vm._data.xxx   
   return vm[target][key];  
  },  
  set(newValue) {   
   // vm.xxx = yyy ===> vm._data.title = yyy   
   vm[target][key] = newValue;  
  } 
 }) 
}
export default proxyData;

Having handled the access problem, we now need to recursively 1 the inner elements of data. obseve (vm._data);

Create a new observe. js:


function observe (data) {
 if (typeof data !== 'object' || data = null) return;
 return new Observer(data); //  If it is an application type, add it directly 1 Observers 
} 

Create a new observer: observer. js


function Observer(data) {
 if (Array.isArray(data)) {
  //  Processing arrays 
   data._proto_ = arrMethods; 
 }
 else {
  //  Processing object 
  this.walks(data);
 }
}
Observer.prototype.walks = function (data) {
 let keys = Object.keys(data); //  Get data All of the following key , and still 1 Array of numbers 
 for (var i = 0 ; i < keys.length ; i++) {  
  var key = keys[i];  
  var value = data[key];  
  defineReactiveData(data, key, value); //  Each regenerated responsive data  
 }}

Create a new reactive. js processing object and other response expressions


function defineReactiveData (data, key, value) { 
 observe(value);  //  The child elements are followed by recursion.  
 Object.defineProperty(data, key, {  
  get() {   
   return value;  
  },  
  set (newValue) {   
   if (newValue === value) return;   
   value = newValue;  //  Trigger a change   
  } 
 }
 )
};

ok, the data hijacking of the object is handled well here, and the rest needs to be handled with arrays

In V2, seven methods of rewriting prototype are used to hijack data.

Hijacking Array:

Create a new Array. js file:


import {ARR_METHODS} from './config.js';  
 // 7 A collection of array methods 
import observeArr from './observeArr.js';
var originArrMethods = Array.prototype, 
arrMethods = Object.create(originArrMethods); 
ARR_METHODS.map(function (m) { 
 arrMethods[m] = function () {  
  var args = Array.prototype.slice.call(arguments); //  Class array to array   
  var rt = originArrMethods[m].apply(this, args);  
  var newArr;  
  switch (m) {   
   case 'push':   
   case 'ushift':     
    newArr = args;   
   case 'splice':    
    newArr = args.slice(2);    
    break;   
   default:     
    break;  };  
  newArr && observeArr(newArr);  
  return rt; 
  } 
}); 
 export { arrMethods }

observeArr (newArr): Arrays may also be nested, so you need to look at the data.


import observe from "./observe";
function observeArr (arr) { 
 for (var i = 0 ; i < arr.length ; i++) {  
  observe(arr[i]); //  Here we go again observe Go.  
 }
}
export default observeArr;

3: Summary

This is the basic process, not just object. defineProperty doing get and set to the data. Summarize the main processes under 1:

(1): At the time of initialization: save 1 instance and mount the instance. Initialize the data through the initState method, mainly data data, but also computed and watch to be processed.

(2): Call initData (); Re-assign data, then execute data, and modify the writing system 1 for users to obtain data attributes to this. xxx and observe (data)

(3): When observe (data), it is necessary to judge data. If it is a reference type, it is necessary to add an observer observer. At the same time, when the observer finally judges whether data is an array or an object, the object directly retriggers object. defineProperty, and at the same time, it re-triggers observe internally. If the array is directly re-7 array methods, and then on the inside of the array observe.

The above is the handwritten Vue 2.0 data hijacking example details, more information about handwritten vue data hijacking please pay attention to other related articles on this site!


Related articles: