【Vue高级】MVVM实现原理(二)—— 数据劫持【Observer】

Vue实现这种数据双向绑定的效果,需要三大模块:

  1. Observer:能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
  2. Compile:对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
  3. Watcher:作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

Observer

Observer的核心是通过Obeject.defineProperty()来监听数据的变动,这个函数内部可以定义setget,每当数据发生变化,就会触发set。这时候Observer就要通知订阅者,订阅者就是Watcher

<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>

 
<body>
    {{a}}
</body>
<script src="./mvvm.js"></script>
<script>
    let vue = new Vue({
        el:'#app',
        data:{
            a:{
                a:1
            }
        }
    })
    console.log(vue)
</script>
</html>

new Vue的时候,会把vue的data属性进行递归,用Object.defineProperty()方法把这些属性全部转成set、get方法 

当data中的某个属性被访问时,则会调用get方法,当data中的属性被改变时,则会调用set方法。

function Vue(options={}){
    this.$options = options;//将所有属性挂载在options
    var data = this._data = this.$options.data;
   
    //观察者  递归处理传进来的data
    observe(data)

    //观察完之后,this代理了this._data  数据代理
    for(let key in data){
        Object.defineProperty(this,key,{
            enumerable:true,
            get(){
                return this._data[key];//获取到新值
            },
            set(newVal){
                this._data[key] = newVal//这里触发观察者【再次执行Observe(data)中的set方法】
            }
        })
    }
}

//观察者  vm.$options
function Observe(data){//这里写我们的主要逻辑
   for(let key in data){//把data属性通过object.defineProperty的方式定义

       let val = data[key]

       observe(val)//递归 使data的中的每个属性都被Object.defineProperty处理

       Object.defineProperty(data,key,{
           enumerable:true,
           get(){
               return val
           },
           set(newVal){//更改值得时候
                if(newVal===val){//设置的值和以前是一样的东西
                    return
                }
                val = newVal//如果以后在获取值得时候,将刚才设置的值丢回去
                observe(newVal)
           }
       })
   }
}
function observe(data){
    if (typeof data !== 'object'){
        return 
    }
    return new Observe(data)
}

①vue特点 不能新增不存在的属性 

    因为不存在的属性 没有 get和set,不能被监控

② 深度响应 因为每次赋予一个新对象时会给这个新对象增加数据劫持

发布了248 篇原创文章 · 获赞 32 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_37899792/article/details/105551784