这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战
在Vue初次渲染过程中有一个比较关键的概念:渲染Watcher,其主要是负责视图的更新,是之后响应式中data和视图之间的核心枢纽
在Vue中存在三种Watcher,分别是Render Watcher(渲染Watcher)、Computed Watcher(Computed)和User Watcher
部分接触Vue不久的小伙伴可能会比较惊讶为何会将Computed和Render Watcher、user Watcher放在一起讨论,因为他们三者在Vue的底层中都是基于Watcher实现的,会通过传递不同的参数来进行区分
首先回顾前文处理初次渲染mountComponent函数做的事情
export function mountComponent(vm, el) {
const options = vm.$options;
vm.$el = el;
vm._update(vm._render());
}
在Vue中每个组件都会创建一个对应的渲染Watcher,当数据变化时视图需要及时响应,将最新的数据渲染至页面上,即响应式
需要对上述代码进行改造
export function mountComponent(vm, el) {
const options = vm.$options;
vm.$el = el; // 真实的DOM元素
/**
* Watcher 就是用来渲染的
* vm._render 通过解析的render方法 渲染出虚拟dom
* vm._update 通过虚拟dom 创建 真实dom
*/
// 无论渲染还是更新 都会执行
let updateComponent = () => {
// vm._render() 返回的是虚拟DOM
vm._update(vm._render());
};
// 渲染 watcher, 每一个组件都有一个watcher
// true 表示他是一个渲染watcher
new Watcher(vm, updateComponent, () => {}, true);
}
需要注意:
- 为何要将
el挂载到vm.$el中,在日常开发中,我们将Vue实例打印出来会发现都有这么一个属性,它的作用是用来记录真实的DOM节点,用于后续存放根据虚拟DOM创建的真实DOM updateComponent函数在首次出创建渲染Watcher是会调用一次,即初次渲染时。若是当data改变时会触发试图的更新,也需要调用此函数进行处理- 需要注意
new Watcher时传递的4个参数,不同的参数可用于区分三种Watcher
mountComponent函数中_render已经实现,_update和Watcher暂未实现,接下来先将Watcher初始化,在此只需要掌握大致的流程和函数的作用即可,具体实现后文再实现
class Watcher {
constructor(vm, exprOrFn, callback, options) {
this.vm = vm;
this.callback = callback;
this.options = options;
this.getter = exprOrFn;
}
// 存储Watcher
get() {}
// 批量更新
update() {}
// 执行存储操作
run() {}
// 添加被观察者
addDep() {}
}
_update实现,次函数作为入口函数的存在,其中并不会做太多的事情,具体通过虚拟DOM创建真实DOM的流程全封装至patch函数中,热门的diff比较就在其中
Vue.prototype._update = function (vnode) {
const vm = this;
// 通过虚拟节点 渲染出来真实dom
// 需要用虚拟节点创建出来真实节点 替换掉 真实的 $el
vm.$el = patch(vm.$el, vnode);
};