vue的响应原理

81 阅读2分钟

一、 几个核心概念

  • 监听器 Observer,用来劫持并监听所有属性(转变成setter/getter形式),如果属性发生变化,就通知订阅者
  • 订阅器 Dep,用来收集订阅者,对监听其Observer和订阅者Watcher进行统一管理
  • 订阅者 Watcher,可以收到属性的变化通知并执行相应的方法,从而更新视图
  • 解析器 Compile,可以解析每个节点的相关指令,对模板数据和订阅器进行初始化

二、 核心流程

  • vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

  • 在初始化调用defineReactive,实例化一个dep负责派发更新,使用Object.definerProperty中的setter负责依赖收集

  • Dep:负责管理Watcher,dep.notify()实际调用watcher中的update,按照需要更新的队列依次更新(按id先后顺序)

  • 调用watcher.before()触发beforeUpdate的hook,最终通过vm._update更新视图(到diff流程中)

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

三、 原理

当创建Vue实例时,vue会遍历data选项的属性,利用Object.defineProperty为属性添加getter和setter对数据的读取进行劫持(getter用来依赖收集,setter用来派发更新),并且在内部追踪依赖,在属性被访问和修改时通知变化。

每个组件实例会有相应的watcher实例,会在组件渲染的过程中记录依赖的所有数据属性(进行依赖收集,还有computed watcher,user watcher实例),之后依赖项被改动时,setter方法会通知依赖与此data的watcher实例重新计算(派发更新),从而使它关联的组件重新渲染。

一句话总结:vue.js采用数据劫持结合发布者-订阅者模式,通过object.defineProperty来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发响应的监听回调;