Интерпретация исходного кода Vue3 (1) — createApp

Vue.js

предисловие

Расстояние от предыдущего постаРазминка интерпретации исходного кодаПрошло больше двух недель.Прошли Национальный день и Праздник Середины Осени.Всех с Праздником Середины Осени и Национальным Днем.Желаю вам никаких багов,не звоните в полицию онлайн,и уходите с работы пораньше каждый день.

Серия статей VUE3 будет объяснена вокруг папки. После завершения основной линии будет выполнена часть объяснения, и исходный код Vue3 будет прочитан и проанализирован один за другим согласно этому принципу.

текст

Здесь начинается текст, и здесь начинается путь к анализу исходного кода Vue3.

createApp

Способ создания приложения в Vue3 — через createApp, который в основном такой же, как и предыдущий метод нового Vue.

@file packages/runtime-dom/src/index.ts
export const createApp = ((...args) => {
  const app = ensureRenderer().createApp(...args)

  if (__DEV__) {
    injectNativeTagCheck(app)
  }

  const { mount } = app
  app.mount = (containerOrSelector: Element | string): any => {
    const container = normalizeContainer(containerOrSelector)
    if (!container) return
    const component = app._component
    if (!isFunction(component) && !component.render && !component.template) {
      component.template = container.innerHTML
    }
    container.innerHTML = ''
    const proxy = mount(container)
    container.removeAttribute('v-cloak')
    container.setAttribute('data-v-app', '')
    return proxy
  }

  return app
}) as CreateAppFunction<Element>

Приведенный выше код createApp — это метод, который мы вызываем при создании приложения.

  • sureRenderer — это функция одноэлементного режима, которая возвращает средство визуализации. Если средство визуализации отсутствует, она вызывает createRenderer для получения средства визуализации и получения экземпляра приложения;
  • Зарегистрируйте метод в среде разработки: isNativeTag, смонтируйте его под app.config;
  • Получите метод монтирования экземпляра и сохраните его;
  • Переопределить метод монтажа экземпляра;
    • Вызовите normalizeContainer, чтобы получить контейнер корневого элемента;
    • Оцените шаблон и получите шаблон, который необходимо отрендерить;
    • Очистите innerHTML контейнера;
    • Вызовите метод монтирования вышеуказанного экземпляра;
    • Удалите атрибут v-cloak и добавьте атрибут data-v-app;
    • Действует после обратного крепления;
  • вернуть экземпляр;
// 上面代码中所使用到的两个简单的函数源码
// @file packages/runtime-dom/src/index.ts
// 获取renderer
let renderer: Renderer<Element> | HydrationRenderer
function ensureRenderer() {
  return renderer || (renderer = createRenderer<Node, Element>(rendererOptions))
}
// normalizeContainer,获取元素
function normalizeContainer(container: Element | string): Element | null {
  if (isString(container)) {
    return document.querySelector(container)
  }
  return container
}

На этом этапе объясняется метод createAPP. Ядро состоит из двух частей, первая часть — реализация вызова createRenderer, вторая часть — реализация метода монтирования экземпляра.

createRenderer

Как упоминалось выше, этот метод вызывается в createAPP для получения объекта рендерера Давайте посмотрим на его реализацию. createRenderer принимает параметр объекта rendererOptions,const rendererOptions = extend({ patchProp, forcePatchProp }, nodeOps)

NodeOps и node-ops в Vue2 имеют схожие функции, но они были оптимизированы в Vue3, добавлены патчи и клоны к nodeOps и удалены некоторые функции;

// @file packages/runtime-core/src/renderer.ts
export function createRenderer<HostNode = RendererNode,
    HostElement = RendererElement>(options: RendererOptions<HostNode, HostElement>) {
    return baseCreateRenderer<HostNode, HostElement>(options)
}

Реализация baseCreateRenderer выглядит следующим образом:

// @file packages/runtime-core/src/renderer.ts
function baseCreateRenderer(
    options: RendererOptions,
    createHydrationFns?: typeof createHydrationFunctions
): any {
	
    // balabala,一堆函数的声明

	return {
        render,
        hydrate,
        createApp: createAppAPI(render, hydrate)
    }
}

Вы можете видеть приведенный выше код, окончательный результат — это функция рендеринга, функция гидрата и функция createApp Функция createApp получается путем вызова createAppAPI.

// @file packages/runtime-core/src/apiCreateApp.ts
export function createAppContext(): AppContext {
  return {
    app: null as any,
    config: {
      isNativeTag: NO,
      performance: false,
      globalProperties: {},
      optionMergeStrategies: {},
      isCustomElement: NO,
      errorHandler: undefined,
      warnHandler: undefined
    },
    mixins: [],
    components: {},
    directives: {},
    provides: Object.create(null)
  }
}

export function createAppAPI<HostElement>(
  render: RootRenderFunction,
  hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement> {
  return function createApp(rootComponent, rootProps = null) {
    if (rootProps != null && !isObject(rootProps)) {
      __DEV__ && warn(`root props passed to app.mount() must be an object.`)
      rootProps = null
    }

    const context = createAppContext()
    const installedPlugins = new Set()

    let isMounted = false
    const app: App = (context.app = {
      _uid: uid++,
      _component: rootComponent as ConcreteComponent,
      _props: rootProps,
      _container: null,
      _context: context,

      version,

      get config() {
        return context.config
      },

      set config(v) {
        if (__DEV__) {
          warn(
            `app.config cannot be replaced. Modify individual options instead.`
          )
        }
      },
      use() {},
      mixin() {},
      component() {},
      directive() {},
      mount() {},
      unmount() {},
      provide() {}
    })
    return app
  }
}

Как указано выше, это исходный код CreateAppapi, и напрямую возвращает функцию Cretapp. CreateApp:

  • Проверьте второй переданный параметр, который является root props;
  • Вызовите createAppContext, чтобы создать объект appContext и присвоить его контексту;
  • Создайте переменную InstallPlugins, Set type, для хранения установленных плагинов;
  • isMounted имеет значение false;
  • Создать приложение, смонтировать свойства и функции;
  • вернуть приложение;

Приложение в настоящее время находится на стадии подготовки Vue, и функции, которые необходимо использовать, подготовлены для следующих операций, таких как монтирование.

mount

Самые основные (тривиальные) операции находятся в монтировании, которое включает в себя все основные функции Vnode, рендеринга, патча и так далее. Давайте сначала посмотрим на процесс вызова mount.

  • Первый шаг: вызовите функцию монтирования в index.ts под runtime-dom;
  • Шаг 2: Вызовите функцию монтирования в apiCreateApp под runtime-core;

Первые два шага аналогичны вызовам в Vue 2. Сначала вызывается монтирование, связанное с платформой, а затем вызывается монтирование, связанное с ядром;

  • Шаг 3: вызов createVNode напрямую; в отличие от Vue2, 2 не вызывает напрямую, а создает наблюдатель, который вызывается, когда наблюдатель используется для вызова get, подробности можно увидетьИнтерпретация исходного кода Vue2 (семь) — крепление
  • Шаг 4: Вызовите рендеринг, чтобы определить, следует ли удалить или рендерить;
  • Шаг 5: Вызовите patch, выполните dom diff и визуализируйте страницу.

Эпилог

Эта статья представляет собой простое начало, а затем будет подробно проанализирована и интерпретирована часть крепления.

Дорога длинна и длинна, я буду ходить вверх и вниз искать

Я слышал, что компания React недавно выпустила официальную библиотеку управления состоянием для recoil, которая упрощает управление состоянием Я с нетерпением жду продолжения Vue.