vue响应原理详解(一看就懂)

vue响应原理详解(一看就懂)

vue相应原理依靠的是Object的defineProperty方法,

该方法提供了给对象定义一个新属性,和修改现有属性的操作

defineProperty方法,参数为对象 、操作的属性 、 和属性描述

其中属性描述可以控制对象的修改,删除,迭代

1、value定义了操作的属性值

2、默认情况下defineProperty新增的属性writable为false代表着不可修改该属性,为true时则可以修改该属性

3、默认情况下defineProperty新增的属性configurable为false代表着不可删除该属性,为true时则可以删除该属性

4、默认情况下defineProperty新增的属性enumrable为false代表着不可迭代该属性,为true时则可以迭代该属性

defineProperty方法在执行的修改新增的同时可以添加get与set方法

get与set方法实现了vue的双向绑定,当我们去查看defineProperty方法定义的属性时,会自动的调用get方法此时可以return我们想要输出的变量,set方法则是在修改时触发,但我们无法确定修改后的属性是否和原属性一致,为了不出现多余的修改,可以添加if判断如果新值与旧值相同则不去修改赋值。

不过如果确认使用get和set方法,因为是借由get/set操作的查看与修改的过程,那么原来的defineProperty的value和writable方法都不可使用了,会出现冲突报错。

由此产生了一个问题,如果说我们监听一个属性那么很容易,但如果是多个属性那么我们怎么办那,总不能每次的新属性都去在写一次defineProperty方法吧。

这时es6类的概念就派上了用场,解决多个属性监听所使用的方法就是calss

将需要监听的对象传给class类,这个既可以给传入的所有属性都添加get/set方法

那么怎么使用calss类解决的这个问题那,各位看官下面将分为步骤详解

 /*
    需求: 快速监听对象中所有属性的变化
    * */
    let obj = {
        name: 'str',
        // name: {a: 'abc'},
        age: 10
    };

            // 只要将需要监听的那个对象传递给Observer这个类
        // 这个类就可以快速的给传入的对象的所有属性都添加get/set方法
    class Observer{

        // constructor可以接收到new Observer(obj)的传值对象
        constructor(data){
            // 此处调用的observer方法,即将calss传入的对象抛给		observer方法接收
            this.observer(data);
        }
        observer(obj){
            if(obj && typeof obj === 'object'){
                // 遍历取出传入对象的所有属性, 给遍历到的属性都增加get/set方法
                for(let key in obj){
                    this.defineRecative(obj, key, obj[key])
                }
            }
        }
        // obj: 需要操作的对象
        // attr: 需要新增get/set方法的属性
        // value: 需要新增get/set方法属性的取值
        defineRecative(obj, attr, value){
            // 如果属性的取值又是一个对象, 那么也需要给这个对象的所有属性添加get/set方法
            this.observer(value);
            Object.defineProperty(obj, attr, {
                get(){
                    return value;
                },
                // 注意set改用箭头函数的原因是因为this指向
                set:(newValue)=>{
                    if(value !== newValue){
                        // 如果给属性赋值的新值又是一个对象, 那么也需要给这个对象的所有属性添加get/set方法
                        this.observer(newValue);
                        value = newValue;
                        console.log('监听到数据的变化,代表可以更新view层');
                    }
                }
            })
        }
    }
    new Observer(obj);
    // obj.name = '测试';
    // obj.age = 123;
    // obj.name.a = '对象a的修改';
    obj.name = {a: '测试'};
    obj.name.a = '对象a的修改';

这其实也变相解释了为何vue的数据会丢失,因为defineProperty方法可以监听对象的数据变化,而数组的却不能很好的去处理,感兴趣的可以去百度一下

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值