Vue2中响应式系统的底层细节。

Vue2中响应式系统的底层细节。

vue2是利用Object.defineProperty方法劫持对象或对象的属性的访问器,在属性值发生变化时获取属性值变化, 从而进行后续操作。这个方法有三个参数,第一个参数obj表示要定义的对象,第二个参数prop表示对象的某个属性值,用字符串表示,第三个参数descriptor是用来控制prop的,重点介绍一下第三个参数,它传入一个对象,对象包括以下的属性值:

value:给prop属性赋值

enumerable:控制属性是否可被遍历,默认是false

writeable:控制属性是否可以被修改,默认是false

configurable:控制属性是否可以被删除,默认是false

get():当程序读取prop属性的时候,get函数(getter)就会被调用

set():当程序修改prop属性的时候,set函数(setter)就会被调用

数据代理

数据代理就是通过一个对象去代理另外一个对象中属性的操作(读/写),下面通过defineProperty方法实现一下数据代理:

function MVVM(options) {

    // 将选项对象保存到vm

    this.$options = options;

    // 将data对象保存到vm和data变量中

    var data = this._data = this.$options.data;

    //将vm保存在me变量中

    var me = this;

    // 遍历data中所有属性

    Object.keys(data).forEach(function (key) { // 属性名: name

        // 对指定属性实现代理

        me._proxy(key);

    });

    // 对data进行监视

    observe(data, this);

    // 创建一个用来编译模板的compile对象

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

}

MVVM.prototype = {

    $watch: function (key, cb, options) {

        new Watcher(this, key, cb);

    },

    // 对指定属性实现代理

    _proxy: function (key) {

        // 保存vm

        var me = this;

        // 给vm添加指定属性名的属性(使用属性描述)

        Object.defineProperty(me, key, {

            configurable: false, // 不能再重新定义

            enumerable: true, // 可以枚举

            // 当通过vm.name读取属性值时自动调用

            get: function proxyGetter() {

                // 读取data中对应属性值返回(实现代理读操作)

                return me._data[key];

            },

            // 当通过vm.name = 'xxx'时自动调用

            set: function proxySetter(newVal) {

                // 将最新的值保存到data中对应的属性上(实现代理写操作)

                me._data[key] = newVal;

            }

        });

    }

};

基本实现流程

(1)通过 Object.defineProperty()给 vm 添加与 data 对象的属性对应的属性描述符

(2)所有添加的属性都包含 getter/setter

(3) getter/setter 内部去操作 data 中对应的属性数据

3.Vue中的数据代理

是通过vm实例对象来代理data对象中属性的读取和修改,这样的好处就是更加方便的操作data中的数据,他的基本原理是通过Object.defindProprerty

方法把data所有属性都添加到vm实例对象上,为添加到vm实例对象的每一个属性都指定一个getter/setter,在getter和setter内部去读写data中对应的属性。

每当要修改的Vue中data对应的属性值,就会触发vm中对应属性的set方法,同时去更新View层视图的值,这就是Vue中的响应式原理,但是defindProperty()方法中没有定义属性值添加/删除的方法,当要往data中添加或者删除的时候,defindProerty()无法完成响应式,这个问题在Vue3中得到了改善。Vue2也提供了完整的解决方案,可通过Vue.set()/this.$set()添加属性,Vue.delete()/this.$delete()删除属性

总结一下,今天讲了vue2中数据的响应式是通过数据代理完成的,而数据代理的主要核心就是Object.defindProperty()这个方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

重塑这战争

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值