MVVM的实现原理入门了解1-- 数据代理

最近面试都有提到MVVM的实现思想以及实现双向数据绑定的方法 为此查找对应资源 [https://github.com/DMQ/mvvm]

查看了很多资源都说双向数据绑定有以下方法

  1. 发布者-订阅者模式
  2. 脏值查询
  3. 数据劫持

查看对应资源代码发现 该资源的数据绑定 使用的是数据劫持与Vue的数据绑定相同  

为此主要描述我理解的数据劫持实现方法 以及 MVVM实现原理

该资源分为 MVVM.js、observer.js、compile.js、watcher.js等四个文件 

主要实现了

  • 数据代理  也就是 用 mvvm.xxx = mvvm.data.xxx  
  • 数据绑定  也就是使用数据劫持实现数据绑定
  • 模板解析  也就是通过对el所绑定的div中的所有元素进行解析v-指令、事件指令与{{}}表达式

MVVM.js

function MVVM(options) {
    this.$options = options || {};
    var data = this._data = this.$options.data; 
    var me = this;  
    //进行数据代理
    Object.keys(data).forEach(function(key) { 
        me._proxyData(key); 
    });
    //进行数据绑定
    observe(data, this);
    //进行模板解析
    this.$compile = new Compile(options.el || document.body, this)
}

MVVM.prototype = {
    _proxyData: function(key, setter, getter) {
        var me = this;
        setter = setter ||
        Object.defineProperty(me, key, {
            configurable: false, 
            enumerable: true, 
            get: function proxyGetter() {
                return me._data[key]; 
            },
            set: function proxySetter(newVal) {
                me._data[key] = newVal;
            }
        });
    }
};

MVVM文件理解 

创建MVVM构造函数 传入的option为传入的对象 如下面出入的data、el等

var vm = new MVVM({
    el: '#mvvm-app',
    data: {
        someStr: 'hello ',
        htmlStr: '<span style="color: #f00;">red</span>',
        child: {
            someStr: 'World !'
        }
    },
}
  1. 进行数据存储 将option存储在MVVM的上 也就是this.$options = options || {}; var data = this._data = this.$options.data; var me = this; 
  2. 遍历存储在mvvm上的data中的所有属性 并将属性作为参数传递给MVVM.prototype._proxyData方法 主要用于数据代理
    1. _proxyData方法 参数1为接收的data中的属性 参数2、3都为自定义的getter、setter方法  
    2. 为每个key也就是data中的属性添加setter 如果形参中有就调用形参的 没有调用object.defineProperty方法
    3. Object.defineProperty(me, key, { configurable: false, enumerable: true, get: function proxyGetter() { return me._data[key]; }, set: function proxySetter(newVal) { me._data[key] = newVal; } });     主要功能是为其添加get与set  (get为查询时触发、set为数据改变时触发)    
      1. 查询时调用get -->   me._data[key]; 
        //使用vm.属性名 读取数据的时候 调用这个方法 
        // 读取this._data中key的属性值 this指向为mvvm
      2. 数据改变时触发set -->  me._data[key] = newVal;
        //如果vm.属性名 = newVal 调用这个方法 
        // 设置this._data中的key的属性值 = newVal

 

posted @ 2019-04-21 09:24  嘿!巴扎嘿  阅读(43)  评论(0)    收藏  举报