4.4 虚拟Vnode映射成真实DOM - update
回到 updateComponent
的最后一个过程,虚拟的DOM
树virtual dom
生成后,调用Vue
原型上_update
方法,将虚拟DOM
映射成为真实的DOM
。
updateComponent = function () {
// render生成虚拟DOM,update渲染真实DOM
vm._update(vm._render(), hydrating);
};
从源码上可以知道,update
主要有两个调用时机,一个是初次数据渲染时,另一个是数据更新时触发真实DOM
更新。这一节只分析初次渲染的操作,数据更新放到响应式系统中展开。
function lifecycleMixin() {
Vue.prototype._update = function (vnode, hydrating) {
var vm = this;
var prevEl = vm.$el;
var prevVnode = vm._vnode; // prevVnode为旧vnode节点
// 通过是否有旧节点判断是初次渲染还是数据更新
if (!prevVnode) {
// 初次渲染
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false)
} else {
// 数据更新
vm.$el = vm.__patch__(prevVnode, vnode);
}
}
update
的核心是patch
方法,而_patch
来源于:
// 浏览器端才有DOM,服务端没有dom,所以patch为一个空函数
Vue.prototype.__patch__ = inBrowser ? patch : noop;
patch
方法又是createPatchFunction
方法的返回值,createPatchFunction
内部定义了一系列辅助的方法,但其核心是通过调用createEle
方法,createEle
会调用一系列封装好的原生DOM
的API
进行dom
操作,创建节点,插入子节点,递归创建一个完整的DOM
树并插入到Body
中。这部分逻辑分支较为复杂,在源码上打debugger
并根据实际场景跑不同的分支有助于理解这部分的逻辑。内容较多就不一一展开。