关于一些Vue的文章。(3)

原文链接我的blog,欢迎STAR。

这次和想要大家分享的一篇文章解析Vue diff 算法

在上篇里,我们提到在渲染时,render>template>el,但是最终,我们得到的都是render函数,那么render函数的作用是什么?接下来该干什么?

带着两个问题,我们深入源码。


首先来解决第一个问题:

 vm._watch = new Watch(vm, updateComponent, noop)

然后找到updateComponent

 updateComponent = () => {
    vm._update(vm._render(), hydrating)
 }
这里写图片描述
这里写图片描述

意思是,通过Watcher的绑定,当数据发生变化时,会执行updateComponent方法,根据不同的条件,调用的updateComponent也不同,在开发环境下,主要调用的是else
里的updateComponent方法,意思是在执行vm._update方法之前会先执行vm._render()方法。

接着找到vm._render()方法,在src/core/instance/render.js文件里,有这么一段代码:

这里写图片描述
这里写图片描述

vm._render方法里,会得到一个VNode对象。至此,第一个问题解决,但是VNode, 又是什么?将在解决第二个问题时,解决。


  • 在已经知晓render函数会得到VNode对象,那么VNode又是什么,下一步又将做什么?

关于VNode, 其实就是Vue.js 2.0 的 Virtual DOM对象,

/src/core/vdom/vnode.js中,可以看到

VNode具体的一些数据:

这里写图片描述
这里写图片描述

这些数据,既是对DOM节点的一些描述。

如果你有兴趣,可以做个实验,瞧瞧真实DOM对象,

 const div = document.createElement('div')
 for (let k in div) {
     console.log(k)
 }

倘若每次都生成一个DOM,对性能该是多大的浪费。

于是我们总结出VNode其实Virtual DOM对象,就是用一个简单一点的对象去代替复杂的dom对象。生成VNode,Virtual DOM对象之后,接下来,需要通过DOM Diff,生成真正的DOM节点。

关于DOM diff 说简单点,其实就是所有的变动先发生在Virtual DOM对象上,然后再将实际发生改变的部分反应到真实DOM上。

值得注意的一点是,比较只会在同级进行,并不会跨层级比较

引用来自React’s diff algorithm的一张图:

这里写图片描述
这里写图片描述

分析源码,在/src/core/vdom/patch.js的patch方法中:

 function patch(oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {
    // ... 
}

patch函数接收六个参数:

oldVnode: 旧的Virtual DOM或者旧的真实DOM;

vnode:新的Virtual DOM;

hydrating : 是否与真实DOM混合;

removeOnly: 这个在源码里有提到,removeOnly is a special flag used only by <transition-group>也就是说是特殊的flag,用于transition-group组件;

parentElm: 父节点;

refElm: 新节点插入到refElm之前。

分析具体实现思路:

  • 如果vnode不存在,oldVnode 存在,此时需要销毁oldVnode
    if (isUndef(vnode)) {
        if (isDef(oldVnode)) invokeDestoryHook(oldVnode)
        return
    }

invokeDestroyHook()方法也就是来销毁节点的一个方法。

  • 如果oldVnode不存在,vnode存在,需要调用createElm()方法创建新节点
    if (isUndef(oldVnode)) {
        isInitialpatch = true
        createElm(vnode, inserteVnodeQueue, parentElm, refElm)
    }

isInitialpatch = true 主要用来作延迟插入处理。

  • 如果vnodeoldVnode 都存在:

    • 如果oldVnode不为真实节点,且 oldVnodevnode是同一节点,那么调用patchVnode()方法,(patchVnode稍后详细讲解)。
    const isRealElement = isDef(oldVnode.nodeType)
    if (!isRealElement && sameVnode(old, vnode)) {
       patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)  
    }
    
    • 如果不为同一节点时,当oldVnode是真实节点,并且是元素节点,且含有server-render属性的时候,移除server-render属性,把hydrating 设置为 true,并调用hydrate函数,将Virtual DOM与真实DOM之间进行映射,然后将oldVnode设置为对应的Virtual DOM,找到oldVnode.elm的父节点,根据vnode创建一个真实DOM节点,并插入到该父节点的oldVnode.elm的位置。
  • 最后返回 vnode.elm, 那么和最开始进如的vnode.el 有什么区别在哪?
    其实很简单,因为最开始作为参数传进去的是新的Virtual DOM对象,也就是说不是真实DOM,再具体点,就是 vnode.elm = null. 经过函数返回以后,现在引用的是对应的真实dom。

至此,完成一个patch过程。

下篇里,将从源码解析patchVnode()以及updateChildren()方法。

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容