流程图

image.png

通过流程图我们可以大概了解我们定义在vue的data数据是如何被一步一步的使用和处理的、下面我们在通过文字整理下这个过程!

  • initData()

    我们在new Vue() 的时候会先执行_init方法、然后就会做一些api做初始化工作、包括一些基础的对象挂载比如$options、$root $children $parent等等、这里面最重要的是执行initState()、主要做一些初始化props、和initMethods、还有最重要的调用initData()、执行initData()主要就是判断当前Data是否是函数如果是函数会去执行函数得到最终的监听数据对象、并且调用proxy方法代理挂载__data(this._data)、得到最终的data后调用observe、并把 _data 传入下去

  • observe()

    observe首先判断当前数据是否是响应式、不是响应式就去new Observer(data)、传入整个data、这个时候会判断当前传入的对象 是否是数组、如果是数组会去执行数组原型链重写方法 arrayMethods (主要重写了7个改变原数组的方法) 重写的目的还是为了去通知页面更新、然后调用this.observeArray()方法、循环数组的每一项进行重新执行observe方法、目的是给数组里面的对象也添加响应式 如果是对象 、那么会调用this.walk(data)方法这个时候会遍历整个对象、拿到对应的 key 去调用defineReactive( obj, key )

  • defineReactive

    defineReactive接收源对象和对应的key、然后给当前这个属性的value继续调用observe方法进行递归监听、然后会为每一个属性创建一个Dep进行收集依赖、然后通过使用Object.defineProperty()方法对属性进行劫持监听、里面会去写get set方法逻辑、在get的时候回去收集依赖关系、然后在set的时候去派发更新、最终会通知到页面的watcher、然后页面watcher会进执行update方法进行更新操作! 这里是这样的、就是整个初始化过程中、同步执行、这个时候defineReactive里面的作用域会和Object.defineProperty的set、get形成闭包、然后会等调用mountComponent() 方法创建页面Watcher的时候执行vm._render() 去触发数据劫持get的操作、因为那个时候需要初始化模板节点里面绑定的数据、这样就会先去 创建页面Watcher 在初始化的模板节点的时候触发get收集依赖到Dep、在Dep里面把当前页面Watcher保存到一个subs队列里面去、然后在set的时候调用队列的Watcher 通知他进行页面更新!

image.png