VUE3源码-CreateApp与mount

本文详细解析了Vue 3中createApp函数的作用,包括初始化渲染器、响应式配置检查,以及关键的mount方法。深入探讨了虚拟DOM挂载、createVNode生成和hydrate/render过程。
摘要由CSDN通过智能技术生成

目录

createApp源码

ensureRenderer

injectNativeTagCheck

injectCompilerOptionsCheck

mount源码

normalizeContainer

mount

createVNode

hydrate 与  render


vue3中实例化一个vue,是从createApp开始的,那我们createApp到底做了啥呢?

createApp源码

const createApp = ((...args) => {
      const app = ensureRenderer().createApp(...args);
      {
          injectNativeTagCheck(app);
          injectCompilerOptionsCheck(app);
      }
      const { mount } = app;
      app.mount = (containerOrSelector) => {...};
      return app;
  });

ensureRenderer

初始化 一些方法(主要是渲染相关的方法),初始化一个app对象

 function baseCreateRenderer(options, createHydrationFns)
    ... 初始化了一些方法
     const internals = {
          p: patch,
          um: unmount,
          m: move,
          r: remove,
          mt: mountComponent,
          mc: mountChildren,
          pc: patchChildren,
          pbc: patchBlockChildren,
          n: getNextHostNode,
          o: options
      };
      let hydrate;
      let hydrateNode;
      if (createHydrationFns) {
          [hydrate, hydrateNode] = createHydrationFns(internals);
      }
      return {
          render,
          hydrate,
          createApp: createAppAPI(render, hydrate)
      };
}
function createAppAPI(render, hydrate) {
      return function createApp(rootComponent, rootProps = null) {
          //此处简化
          const context = {
                  app: {
                    _uid: uid++,
                    _component: rootComponent,
                    _props: rootProps,
                    _container: null,
                    _context: context,
                    _instance: null,
                    version,
                    get config() { return context.config;},
                    set config(v) {...},
                    use(plugin, ...options) {...},
                    mixin(mixin) {...},
                    directive(name, directive) {...},
                    mount(rootContainer, isHydrate, isSVG) {...},
                    unmount() {...},
                    provide(key, value) {...}
                  },
                  config: {
                    isNativeTag: NO,
                    performance: false,
                    globalProperties: {},
                    optionMergeStrategies: {},
                    errorHandler: undefined,
                    warnHandler: undefined,
                    compilerOptions: {}
                  },
                  mixins: [],
                  components: {},
                  directives: {},
                  provides: Object.create(null),
                  optionsCache: new WeakMap(),
                  propsCache: new WeakMap(),
                  emitsCache: new WeakMap()
                };
        return context.app;
    }
  }

injectNativeTagCheck

对app.config.isNativeTag 做响应式处理

      Object.defineProperty(app.config, 'isNativeTag', {
          value: (tag) => isHTMLTag(tag) || isSVGTag(tag),
          writable: false
      });

injectCompilerOptionsCheck

和 injectNativeTagCheck 差不多,对 app.config.isCustomElement 和  app.config.compilerOptions 做响应式只读处理。

mount源码

      
      const { mount } = app;
      app.mount = (containerOrSelector) => {
          const container = normalizeContainer(containerOrSelector);
          if (!container)
              return;
          const component = app._component;
          if (!isFunction(component) && !component.render && !component.template) {
              // __UNSAFE__
              // Reason: potential execution of JS expressions in in-DOM template.
              // The user must make sure the in-DOM template is trusted. If it's
              // rendered by the server, the template should not contain any user data.
              component.template = container.innerHTML;
          }
          // clear content before mounting
          container.innerHTML = '';
          const proxy = mount(container, false, container instanceof SVGElement);
          if (container instanceof Element) {
              container.removeAttribute('v-cloak');
              container.setAttribute('data-v-app', '');
          }
          return proxy;
      };

normalizeContainer

获取挂载位置,源码简化:

return isString(container) ? document.querySelector(container) : container;

mount

挂载

            mount(rootContainer, isHydrate, isSVG) {
                  if (!isMounted) {
                      const vnode = createVNode(rootComponent, rootProps);
                      // store app context on the root VNode.
                      // this will be set on the root instance on initial mount.
                      vnode.appContext = context;
                      // HMR root reload
                      {
                          context.reload = () => {
                              render(cloneVNode(vnode), rootContainer, isSVG);
                          };
                      }
                      if (isHydrate && hydrate) {
                          hydrate(vnode, rootContainer);
                      }
                      else {
                          render(vnode, rootContainer, isSVG);
                      }
                      isMounted = true;
                      app._container = rootContainer;
                      rootContainer.__vue_app__ = app;
                      {
                          app._instance = vnode.component;
                          devtoolsInitApp(app, version);
                      }
                      return getExposeProxy(vnode.component) || vnode.component.proxy;
                  }else {报错}
              }

createVNode

生成一个虚拟dom【vnode】

hydrate 与  render

挂载虚拟dom

(1)先 ensureRenderer【初始化 一些方法(主要是渲染相关的方法)】;

(2)再patch。patch 方法,主要是 mountElement 和 patchElement;

  • mountElement 挂载,挂载时走这一步,onBeforeMount和 onMounted;
  • patchElement 更新时,走这一步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值