vue笔记

68 阅读2分钟

vue 异步更新

  • 1、dep.notify()
  • 2、watch.update()
  • 3、queueWatcher => nexttick(flushSchedulerQueue)
  • 4、timerFunc() promise MutationObserver setImmediate, setTimeout
  • 5、flushCallbacks()
  • 6、flushSchedulerQueue()
  • 7、watch.run()
  • 8、watch.get()

patch算法

1._update -> patch createPatchFunction 2. patch 1、新节点不存在,老节点存在,调用 destroy,销毁老节点 2、如果 oldVnode 是真实元素,则表示首次渲染,创建新节点,并插入 body,然后移除老节点 3、如果 oldVnode 不是真实元素,则表示更新阶段,执行 patchVnode

3.patchVnode 更新节点

  • 全量的属性更新
  • 如果新老节点都有孩子,则递归执行 diff
  • 如果新节点有孩子,老节点没孩子,则新增新节点的这些孩子节点
  • 如果老节点有孩子,新节点没孩子,则删除老节点的这些孩子
  • 更新文本节点 4.updateChildren diff 过程:
  • diff 优化:做了四种假设,假设新老节点开头结尾有相同节点的情况,一旦命中假设,就避免了一次循环,以提高执行效率
  • 如果不幸没有命中假设,则执行遍历,从老节点中找到新开始节点
  • 找到相同节点,则执行 patchVnode,然后将老节点移动到正确的位置
  • 如果老节点先于新节点遍历结束,则剩余的新节点执行新增节点操作
  • 如果新节点先于老节点遍历结束,则剩余的老节点执行删除操作,移除这些老节点

Vue 的 patch 算法有三个作用:负责首次渲染和后续更新或者销毁组件

  • 如果新的 VNode 不存在,老的 VNode 存在,则调用 destroy,销毁老节点

  • 如果老的 VNode 是真实元素,则表示首次渲染,创建整棵 DOM 树,并插入 body,然后移除老的模版节点

  • 如果老的 VNode 不是真实元素,并且新的 VNode 也存在,则表示更新阶段,执行 patchVnode

    • 如果新的 VNode 有孩子,老的 VNode 没孩子,则新增这些新孩子节点
    • 如果老的 VNode 有孩子,新的 VNode 没孩子,则删除这些老孩子节点
    • 更新文本节点
    • 如果新老 VNode 都有孩子,则递归执行 updateChildren,进行 diff 过程
      • 同层比较(降低时间复杂度)深度优先(递归)
      • 而且前端很少有完全打乱节点顺序的情况,所以做了四种假设,假设新老 VNode 的开头结尾存在相同节点,一旦命中假设,就避免了一次循环,降低了 diff 的时间复杂度,提高执行效率。如果不幸没有命中假设,则执行遍历,从老的 VNode 中找到新的 VNode 的开始节点
      • 找到相同节点,则执行 patchVnode,然后将老节点移动到正确的位置
      • 如果老的 VNode 先于新的 VNode 遍历结束,则剩余的新的 VNode 执行新增节点操作
      • 如果新的 VNode 先于老的 VNode 遍历结束,则剩余的老的 VNode 执行删除操纵,移除这些老节点