vue虚拟dom

在vue2.0渲染层做了根本性的改动,那就是引入了虚拟dom。vdom算法是基于snabbdom算法所做的修改
每次更新视图的时候都会使用vdom
源码分析:vm实例挂载到dom上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
src/core/instance/init.js
Vue.prototype._init = function(){
vm.$mount(vm.$options.el)
}
实际上调用的是src/core/instance/lifecycle.js中的mountComponent方法
export function mountComponent(vm:Component,el:?Element,hydrating?:boolean):Component{
vm.$el = el;
if(!vm.$options.render){
vm.$options.render = createEmptyVNode
}
callHook(vm,'beforeMount')
let updateComponent
if(process.env.NODE_ENV !== 'production' && config.performance && mark){

}else{
updateComponent = ()=>{
//vm._render方法会返回一个新的vnode,vm._update就用这个新的vnode和老的vnode进行diff
vm._update(vm._render(),hydrating)
}
}
//在求值的过程中this.value = this.lazy ? undefined : this.get(),
//会调用this.get()方法,因此在实例化的过程当中Dep.target会被设为这个watcher
vm._watcher = new Watcher(vm,updateComponent,noop)
hydrating = false
if(vm.$vnode == null){
vm._isMounted = true
callHook(vm,'mounted')
}
return vm
}

一旦model中的响应式的数据发生了变化,这些响应式的数据所维护的dep数组便会调用dep.notify()方法完成所有依赖遍历执行的工作,这里面就包括了视图的更新即updateComponent方法,它是在mountComponent中的定义的。
完成视图的更新工作事实上就是调用了vm._update方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Vue.prototype._update = function(vnode: VNode, hydrating?: boolean){
const vm:Component = this
if(vm._isMounted){
callHook(vm,'beforeUpdate')
}
const prevEL = vm.$el
const prevVnode = vm._vnode
const prevActiveInstance = activeInstance
activeInstance = vm
//新的vnode
vm._vnode = vnode
if(!prevVnode){
vm.$el = vm.__patch__(vm.$el,vnode,bydrating,false,
vm.$options._parentElm,
vm.$options._refElm
)
}else{
vm.$el = vm.__patch__(prevVnode,vnode)
}
activeInstance = prevActiveInstance
if(prevEL){
prevEL.__vue__ = null
}
if(vm.$el){
vm.$el.__vue__ = vm
}
if(vm.$vnode && vm.$parent && vm.$node === vm.$parent._node){
vm.$parent.$el = vm.$el
}
}