Vue2数据双向绑定原理

数据双向绑定原理

  • 思路:Vue内部通过(数据劫持)Object.defineProperty方法劫持各个属性的setter,getter,结合发布者-订阅者模式的方式,当数据变化时触发相应监听回调通知视图更新。
let oldArrayPrototype=Array.prototype;//先拿到原来数组原型上的方法
let proto=Object.create(oldArrayPrototype);//克隆数组原型对象
    ['push','shift','unshift','pop','reverse','sort'].array.forEach(method => {
        proto[method]=function(){//给克隆出来的对象重新写方法,不会影响数组原型
        //函数劫持,把函数进行重写,但内部继续调用老的方法
            updateView();//更新视图,切片编程
            oldArrayPrototype[method].call(this,...arguments);
        }

    });
    //把一个对象的每一属性都转化成可观测对象
    function observer(target) {
        if(typeof target !=='object'||target===null){//如果不是对象直接返回
            return target;
        }
        if(Array.isArray(target)){
            /* 拦截数组,给数组的方法进行了重写.如果target是数组,则让它的原型链可以找的到proto,即可实现调用数组方法时找到proto重写的数组方法proto[method] */
            Object.setPrototypeof(target,proto);//ES6语法,如果不支持ES6语法,可以写个循环赋值给target
            // target.__proto__=proto;
             for(let i = 0; i< target.length ;i++){
                 observer(target[i]);
             }
        }else{
            for (let key in target) {//对对象的劫持
                defineRective(target,key,target[key]);//每个函数都有一个value属性,利用这个方法重新定义对象的属性和值
            }
        }
    }
    //使一个对象转化成可观测对象
    function defineRective(target,key,value) {//静态属性target:全局唯一的Watcher
        observer(value);/* 若当前value是对象,则继续拦截重新观察,变成被观察后的结果返回再赋值给里面,实现递归调用。但若数据层级较深,会出现递归使内存增大 */
        object.defineProperty(target,key,{//get和set应当操作共同的值
            get(){//get中会进行依赖收集,负责收集订阅者,然后当数据变化的时候后执行对应订阅者的更新函数。
                return value;//获取时直接返回旧的值
            },
            set(newValue){
                observer(newValue);//新赋的值也有可能是对象,重新观察
                if(newValue!==value){//如果新的值不等于老的值那么更新视图和值
                    updateView();//数据变化通知所有订阅者
                    value=newValue;
                }
            }
        })
    }
    //缺点1:如果属性不存在,新增的属性不会是响应式的(因为只循环当前存在的属性)

    function updateView() {
        console.log('更新视图');
    }
    //使用Object.defineProperty 就是可以重新定义属性,给属性增加getter和setter
   /*  let data={name:'hhh',age:{n:100}};
    observer{data};//写个方法观察数据,观察完之后去更改数据
    data.name='jw';
    data.age.n=200;
    data.age={n:200};//给age新赋的对象没有被set和get,不会更新
    data.age.n=300; */
    let data={name:'hhh',age:[1,2,3]}
    observer(data);
    data.age.push(4);/* 需要对数组上的方法进行重写 push shift unshift pop push reverse sort,不能直接更改Array.prototype.push=function () {……},因为直接把原型上的方法重写会导致未被观察的数据也会被重写,应该新创建一个方法,让被观察后的对象属性值为数组的话能找到该方法 */
  • vue2双向绑定缺点:
    1. 2.0 默认会递归
    2. 数组改变length 是无效的
    3. 对象不存在的属性不能被拦截
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值