Vue深入-20【Vue2.0源码重写『数据劫持』】

(1).环境配置搭建

1.建立文件,执行命令

npm init -y 
npm i webpack@4.44.1 webpack-cli@3.3.12 webpack-dev-server@3.11.0
yarn add html-webpack-plugin@4.4.1

2.具体文件配置

根目录新建文件webpack.config.js

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

package.json

{
  "name": "webpackdefine-bilibili",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "html-webpack-plugin": "^4.4.1",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  }
}

新建src中的index.js

import Vue from 'vue';
console.log(1)

新建public index.htnl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

新建vue文件夹

index.js

console.log('vue');

npm run dev运行

(2).劫持this.data从而直接能访问data

src index.js

import Vue from 'vue';
let vm = new Vue({
    el:"#app",
    data(){
        return{
            title:'学生列表',
            classNum:'1',
            total:2,
            teacher:['张三','李四'],
            students:[
                {
                    id:1,
                    name:'小红'
                },
                {
                    id:2,
                    name:'小明'
                }
            ]
        }
    }
})

vue index.js

import {initState} from './init'
function Vue(options){
    this._init(options);
}
Vue.prototype._init = function(options){
    var vm = this;
    vm.$options = options;
    initState(vm)
}
export default Vue;

vue init.js

import proxyData from './proxy'
function initState(vm){
    var options = vm.$options;
    if(options.data){
        initData(vm)
    }
}
function initData(vm){
    var data = vm.$options.data;
    vm._data = data = typeof data === 'function' ? data.call(vm) : data || {};
    for(var key in data){
        proxyData(vm,'_data',key)
    }
}
export {
    initState
}

proxy.js

function proxyData(vm,target,key){
    Object.defineProperty(vm,key,{
        get(){
            return vm[target][key]
        },
        set(newValue){
            vm[target][key] = newValue
        }
    })
}
export default proxyData;

此时就已经可以通过console.log(vm.total);直接访问了

(3).对象 观察者

observe.js

import Observer from './observer'
function observer(data){
    if(typeof data!=='object' || data === null) return
    return new Observer(data);
}
export default observer

init.js

import proxyData from './proxy'
import observe from './observe'
function initState(vm){
    var options = vm.$options;
    if(options.data){
        initData(vm)
    }
}
function initData(vm){
    var data = vm.$options.data;
    vm._data = data = typeof data === 'function' ? data.call(vm) : data || {};
    for(var key in data){
        proxyData(vm,'_data',key)
    }
    observe(vm._data)
}
export {
    initState
}

observer.js

import observer from './observe';
import defineReactiveData from './reactive';
function Observer(data){
    if(Array.isArray(data)){

    }else{
        this.walk(data);
    }
}
Observer.prototype.walk = function(data){
    var keys = Object.keys(data);
    for(var i = 0; i < keys.length; i++){
        var key = keys[i],
            value = data[key]
            defineReactiveData(data,key,value)
    }
}
export default Observer

新建reactive.js

import observer from './observe';
function defineReactiveData(data,key,value){
    observer(value);
    Object.difineProperty(data,key,{
        get(){
            console.log("响应获取:",value);
            return value
        },
        set(newValue){
            console.log('响应设置',newValue);
            observer(newValue)
            value = newValue
        }
    })
}
export default defineReactiveData

src index中访问

import Vue from 'vue';
let vm = new Vue({
    el:"#app",
    data(){
        return{
            title:'学生列表',
            classNum:'1',
            total:2,
            info:{
                a:{
                    b:3
                }
            },
            teacher:['张三','李四'],
            students:[
                {
                    id:1,
                    name:'小红'
                },
                {
                    id:2,
                    name:'小明'
                }
            ]
        }
    }
})

console.log(vm.info.a);

 

(4).数组观察者

array.js

import observeArr from './observeArr'
import {ARR_METHODS} from './config'

var originArrMethods = Array.prototype,
    arrMethods = Object.create(originArrMethods);
    ARR_METHODS.map(function(m){
        arrMethods[m] = function(){
            var args = Array.prototype.slice.call(arguments),
                rt = originArrMethods[m].apply(this,args);
                console.log('数组新方法',args);
            var newArr;
            switch(m){
                case 'push':
                case 'unshift':
                    newArr = args;
                    break;
                case 'splice':
                    newArr = args.slice(2);
                    break;
                default:
                    break;            
            }   
            newArr && observeArr(newArr);
            return rt; 
        }
    })
    export{
        arrMethods
    }

config.js

var ARR_METHODS=[
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sort',
    'reverse'
];
export{
    ARR_METHODS
}

observerArr

import observer from './observe'
import observe from './observe'
function observeArr(arr){
    for(var i = 0;i < arr.length; i++){
        observe(arr[i]);
    }
}
export default observeArr;

observer.js

import observer from './observe';
import defineReactiveData from './reactive';
import {arrMethods} from './array';
import observeArr from './observeArr';
function Observer(data){
    if(Array.isArray(data)){
        data.__proto_ = arrMethods;
        observeArr(data)
    }else{
        this.walk(data);
    }
}
Observer.prototype.walk = function(data){
    var keys = Object.keys(data);
    for(var i = 0; i < keys.length; i++){
        var key = keys[i],
            value = data[key]
            defineReactiveData(data,key,value)
    }
}
export default Observer

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值