Vue.js 3.0源码解读:组件的实现-组件更新概述

505 阅读1分钟

我们都知道组件是有模版、组件描述对象、数据构成的,数据的变化会引起组件的更新。组件的渲染过程中创建了一个带副作用的渲染函数,当数据发生变化的时候,就会执行这个渲染函数,触发组件的更新。

副作用渲染函数更新组件的过程

副作用渲染函数是setupRenderEffect:

const setupRenderEffect = (instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized) => {
    instance.update = effect(function componentEffect() {
        if (!instance.isMounted) {
            ...
        }
        else {
          let { next, bu, u, parent, vnode } = instance;
          let originNext = next;
          let vnodeHook;
          {
              pushWarningContext(next || instance.vnode);
          }
          if (next) {
              next.el = vnode.el;
              updateComponentPreRender(instance, next, optimized);
          }
          else {
              next = vnode;
          }
          ...
          const nextTree = renderComponentRoot(instance);
          {
              endMeasure(instance, `render`);
          }
          const prevTree = instance.subTree;
          instance.subTree = nextTree;
          {
              startMeasure(instance, `patch`);
          }
          patch(prevTree, nextTree, 
          // parent may have changed if it's in a teleport
          hostParentNode(prevTree.el), 
          // anchor may have changed if it's in a fragment
          getNextHostNode(prevTree), instance, parentSuspense, isSVG);
          {
              endMeasure(instance, `patch`);
          }
          ...
        }
    }
}

这代码大概的意思,我的理解是:如果组件没有渲染过!instance.isMounted,那就渲染,如果不是,else执行的是更新组件。

if (next) {
  next.el = vnode.el;
  updateComponentPreRender(instance, next, optimized);
}

next表示新的组件vnode,updateComponentPreRender函数是更新组件vnode节点信息。

const nextTree = renderComponentRoot(instance);

这是渲染新的子树vnode。

const prevTree = instance.subTree;

这是缓存旧的子树vnode。之后调用patch的方法,这个是更新组件的核心逻辑。

因此,更新组件主要做了三件事:更新组件vnode节点、渲染新的子树vnode、根据新旧子树vnode执行patch逻辑