vue源码解析之diff原理

4,382 阅读3分钟

源码分析

patch

虚拟dom更新的时候,会执行update,update方法中又会调用patch,根据新旧Vnode对比转换成真正的 DOM 节点,所以diff算法用在patch过程中 patch主要做了四个判断:

  1. 没有新节点,直接触发旧节点的destory钩子;
  2. 没有旧节点,说明是页面刚开始初始化的时候,此时,根本不需要比较了,直接全部都是新建,所以只调用 createElm;
  3. 旧节点和新节点自身一样,通过 sameVnode 判断节点是否一样,一样时,直接调用 patchVnode 去处理这两个节点;
  4. 旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点;

patchVnode

patchVnode主要做了几个判断:

  1. 新节点是否是文本节点,如果是,则直接更新dom的文本内容为新节点的文本内容;
  2. 新节点和旧节点如果都有子节点,则处理比较更新子节点;
  3. 只有新节点有子节点,旧节点没有,那么不用比较了,所有节点都是全新的,所以直接全部新建就好了,新建是指创建出所有新DOM,并且添加进父节点;
  4. 只有旧节点有子节点而新节点没有,说明更新后的页面,旧节点全部都不见了,那么要做的,就是把所有的旧节点删除,也就是直接把DOM 删除;

updateChildren

该方法主要将新旧节点的children数组进行前后指针的对比:

  1. 前面4个条件列出了4中比较结果的处理,如果前面4个条件都不满足,则进行单个遍历查找;
单个遍历查找

拿新子节点的子项,直接去旧子节点数组中遍历,找一样的节点出来流程大概是

  1. 生成旧子节点数组以vnode.key为key的map表;
  2. 拿到新子节点数组中一个子项,判断它的key是否在上面的map中;
  3. 不存在,则新建DOM,并插入oldStartVnode 前面;
  4. 存在,继续判断是否sameVnode,如果相同,直接移动到 oldStartVnode 前面;如果不同,直接创建插入 oldStartVnode 前面;
  5. 处理剩下的节点,新子节点遍历完毕,旧子节点可能还有剩,所以我们要对可能剩下的旧节点进行 批量删除!就是遍历剩下的节点,逐个删除DOM;
  6. 旧子节点遍历完了,新子节点可能有剩,所以要对剩余的新子节点处理,很明显,剩余的新子节点不存在 旧子节点中,所以全部新建;

diff流程图

vue系列课程

最近会陆续的对vue进行源码分析,一系列课程如下:

state系列

  1. props原理
  2. methods原理
  3. data原理
  4. computed原理
  5. watch原理

lifecycle系列

  1. 生命周期原理

event系列

  1. event原理

render系列

  1. render原理

inject/provide系列

  1. inject/provide原理

plugins系列

  1. vue-router原理
  2. Vue Router 那些事
  3. Vuex你应该知道的事
  4. vue源码解析之vuex原理
  5. Vue自定义插件

组件系列

  1. keep-alive原理
  2. Vue 单文件组件
  3. Vue组件间通信
  4. vue虚拟列表

指令系列

  1. Vue自定义指令
  2. vue源码解析之Directives原理

算法系列

  1. diff原理
  2. Vue编译器源码分析

异步任务

  1. vue源码解析之NextTick原理

其他

  1. vue单元测试
  2. Vue轮播组件
  3. 你不知道的vue那些事
  4. vue技巧大解密
  5. 面试-高级前端之VUE数据响应式实现