写在前面
本篇是从零实现vue2系列第五篇,将 YourVue 实例的 render 函数转换成真实 dom 和更新算法。
正文
上篇文章我们把 render 函数挂在了 options 属性上,执行 render()
就可以得到 template 对应的虚拟 dom 树了。
1export default class YourVue{
2 update(){
3 if(this.$options.template){
4 if(this._isMounted){
5 const vnode = this.$options.render()
6 patch(this.vnode, vnode)
7 this.vnode = vnode
8 }else{
9 this.vnode = this.$options.render()
10 let el = this.$options.el
11 this.el = el && query(el)
12 patch(this.vnode, null, this.el)
13 this._isMounted = true
14 }
15 }
16 }
17}
Vue 将虚拟 dom 转换成真实 dom 有两种阶段,一个是 mount,一个是 update。都是通过 patch 函数来操作 dom 的。
1export function patch (oldVnode, vnode, el) {
2 if(isUndef(vnode)){
3 createElm(oldVnode, el)
4 return
5 }
6 if (oldVnode === vnode) {
7 return
8 }
9 if(sameVnode(oldVnode, vnode)){
10 patchVnode(oldVnode, vnode)
11 }else{
12 const parentElm = oldVnode.elm.parentNode;
13 createElm(vnode,parentElm,oldVnode.elm)
14 removeVnodes(parentElm,[oldVnode],0,0)
15 }
16}
如果是 mount 阶段,会执行 createElm,如果是 update 阶段,先判断两个根节点的 vnode 是否相同,如果不同则直接创建新的 dom,如果相同则执行 patchVnode。
先看 mount 阶段的 createElm,就是createElement
和 setAttribute
,updateListeners
就是第一篇文章中事件绑定到 dom 的方法。最后将生成的 dom 插入到指定的位置。