本文总结自: https://segmentfault.com/a/1190000006599500,将每一个流程提炼出来做一个简单的说明,以免自己被繁杂的逻辑弄昏头脑~
observer: 遍历数据并挟持所有属性,为每一个属性创建dep对象(订阅器, 内含数组sub装载订阅者watcher),当属性发生改变的时候通知此dep,并由他告知所有订阅者(即在set方法中调用dep的notify)
备注: 由于dep创建于函数内部,外部无法访问,因此为其添加watcher变得很尴尬,因此先将watcher赋值给全局变量Dep.target,再添加到sub
dep(订阅器): 可添加sub、轮流调用watcher的update方法
compile: 解析所有指令,遍历所有节点和文本,
对于节点,先转为fragment(操作fragment速度比直接操作dom快),再遍历其所有vue属性,例如v-mode,v-on:click。。。
由专门的解析工具compileUtil处理, 对于事件属性(v-on:xxx),创建此节点对应事件的监听函数并创建watcher对象,以回调函数作为其参数,而此回调函数内调用updater的方法进行视图更新。
对于v-model,先赋值在创建监听函数
。。
其他v-class、v-text均有相应处理方式
compileUtil: 一个工具对象,提供不同属性的处理方式
watcher: 是连接observer与compile的桥梁
1.被创建时便调用对应属性的get方法以将自己添加到dep中
2.包含update方法,能调用它的回调函数
3.当dep的notify调用时自己的update方法被调用
updater对象: 更新视图,当watcher的update方法被触发时提供对应的方法更新视图,更改数据。
初始化时:
1.observer挟持所有属性,创建对应dep
2.解析所有指令(遍历节点,遍历属性),节点转fragment对象,创建监听函数,创建watcher对象并添加到dep中,watcher回调函数控制视图更新,数据变化
3.fragment处理完毕后初始化视图
当我们触发被监测的事件(例如click),将: 触发监听函数-->updater更新视图,更改数据-->因为数据被挟持,触发set方法-->通知对应dep-->dep通知所有的watcher更新-->所有回调函数执行-->视图更新
当改变data,将: 因为数据被挟持,触发set方法-->通知对应dep-->dep通知所有watcher更新-->所有回调函数执行-->视图更新