MVVM模式分析之数据代理

      大家想看源码的,有大佬已经在GitHub上写了MVVM,大家有兴趣可以去GitHub搜索MVVM第一个就是,里面是中文。

       具体分析一下如何实现:数据代理。(这些也是前端面试中Vue必问的知识点)

       分析之前大家需要了解一下JavaScript有关对象的方法和属性:

        Object.keys(),给此方法传入一个对象,它会返回一个数组,这个数组中的值是由传入的对象中的K值所组成(K值,KV键值对中的K,K是属性,V是值)。

在MVVM中,在实例化对象中传入配置对象,要将配置对象中的data中的属性拿出来,然后进行遍历

 Object.keys(data).forEach(function(key) {
        // 调用实例原型上的方法,将遍历的属性值添加到当前实例上
        me._proxyData(key);
 });

        Object.defineProperty(),方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。此方法接受三个参数,第一个是目标对象;第二个参数是向目标属性中添加或修改的属性;第三个参数传入一个配置对象,此配置对象中包括:configurable为true,添加或修改的属性值可以被修改或删除,默认值为false,不能修改或删除;enumerable是否能被枚举,设置为true时可以被枚举,设置为false时不能被枚举

 //me是指实例化的那个对象,key中保存的是data中遍历拿到的每一个属性
Object.defineProperty(me, key, {
 //此属性不能被修改
        configurable: false,
//此属性可以被枚举
        enumerable: true,
//将set好的值写入到属性中
        get: function proxyGetter() {
            return me._data[key];
        },
//设置该属性的值为newVal
        set: function proxySetter(newVal) {
            me._data[key] = newVal;
        }
  });

 

数据代理:

        需求:

1、为何要产生数据代理?2、何为数据代理?

        解决:

1、数据代理方便程序员直接使用data中的属性。

2、在Vue语法中,不用vm.data.属性去获取值,而是直接使用{{属性}}向标签中添加文本即可。

      具体实现的步骤:

1、将配置参数对象传入MVVM构造函数中(在Vue中是Vue构造函数,在此篇文章中都使用MVVM构造函数来说明,Vue源码中的实现和MVVM中的类似)。

2、将传入参数指针修改为this.$options,给配置对象设定新的指向,指向其堆内存中。

3、给访问data中的属性设置新的指向,分别为_data和data。

4、将this保存在变量me中。

5、使用对象中的key方法和数组的forEach方法将对象中每一个属性遍历出来

function MVVM(options) {
    // 接受实例的配置参数,配置参数为对象,将对象存在$options方法中
    this.$options = options || {};
    // 将配置对象中的data的动态属性值拿出来赋值给实例_data属性上
    var data = this._data = this.$options.data;
    // 将指向实例this存在me中
    var me = this;

    // 数据代理
    // 实现 vm.xxx -> vm._data.xxx
    Object.keys(data).forEach(function(key) {
        // 调用实例原型上的方法,将遍历的属性值添加到当前实例上
        me._proxyData(key);
    });

    this._initComputed();

    observe(data, this);

    this.$compile = new Compile(options.el || document.body, this)
}

 

6、给构造函数MVVM原型设置方法_proxyData,每个遍历的属性都调用此方法,向me实例中添加属性,并将值赋值给新添加的属性。

MVVM.prototype = {
    constructor: MVVM,
    $watch: function(key, cb, options) {
        new Watcher(this, key, cb);
    },

    // 实例原型上的方法接受三个参数,第一个参数为遍历拿到的属性值,第二个参数为属性的v,
    _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;
            }
        });
    },

总结:

         以上步骤就实现了数据代理,主要使用到了Object对象中的keys方法和defineProperty方法,通过keys方法将data中的每一个属性拿到,在通过defineProperty向new MVVM实例中添加data的属性,此时vm实例就可以直接访问到data中的属性

console.dir(vm._data.msg)
 // 数据代理----Vue中有数据代理
console.log(vm.msg)
// 数据代理:data对象中的数据需要通过vm去访问
// vm是代理者,data是被代理者
// 面试题: 说说你对Vue的理解
    

以后还会分析Vue中的模板解析、数据劫持。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王鹏飞的解忧屋

您的鼓励是我最大的创作来源

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值