preface

The distance from the previous article source code interpretation of preheating more than two weeks of time, spent the National Day and Mid-Autumn Festival, the late Mid-Autumn Festival happy National Day to everyone, I wish you no bug, online do not alarm, work early every day.

Vue3 series of articles will be around the folder to explain, after the main line flow through, and then part of the explanation, will be in accordance with this principle for Vue3 source code one by one reading and analysis.

The body of the

Text from here, Vue3 source analysis road from here,

createApp

Vue3 creates applications using createApp, which is basically the same as new 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>Copy the code

The above code createApp is the method we call when we create the application

  • EnsureRenderer is a singleton function that returns a renderer or, if no renderer is ensureRenderer, call createRenderer to obtain the renderer and obtain an app instance.
  • Dev: register a method isNativeTag and mount it under app.config.
  • Get the mount method of the instance and save it;
  • Override the mount method of the instance;
    • Call normalizeContainer to get the root element container;
    • Determine the template, get the template to render;
    • Empty innerHTML of the container;
    • Call the mount method of the above example;
    • Delete the V-cloak attribute and add the data-v-app attribute.
    • Return to mount agent after;
  • Return instance;
// @file packages/runtime-dom/ SRC /index.ts // Renderer<Element> | HydrationRenderer function ensureRenderer() { return renderer || (renderer = createRenderer<Node, Element > (rendererOptions))} / / normalizeContainer, obtain the Element function normalizeContainer Element (container: | string) : Element | null { if (isString(container)) { return document.querySelector(container) } return container }Copy the code

This completes the createAPP method tutorial. The core consists of two parts. The first part is the implementation of calling createRenderer. The second part is the implementation of the mount method of the instance.

createRenderer

So let’s see how this is implemented when we call this method in createAPP to get the Renderer object. Const rendererOptions = extend({patchProp, forcePatchProp}, nodeOps)

NodeOps has similar functions with node-Ops in Vue2, but it has been optimized in Vue3 by adding patch and Clone to nodeOps and removing some functions.

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

The implementation of baseCreateRenderer is as follows:

// @file packages/runtime-core/src/renderer.ts function baseCreateRenderer( options: RendererOptions, createHydrationFns? : typeof createHydrationFunctions): any {// Balabala, a bunch of functions declare return {render, hydrate, createApp: createAppAPI(render, hydrate) } }Copy the code

You can see the code above, which returns the render function, the hydrate function, and the createApp function, which is obtained by calling 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 } }Copy the code

CreateApp (createAppAPI) createApp (createApp) CreateApp:

  • Validates the second parameter passed in, root props;
  • Call createAppContext to create the appContext object and assign it to the context;
  • Create a variable installedPlugins, of type Set, to store installedPlugins;
  • IsMounted set to false.
  • Create app, mount properties and functions;
  • Return to the app;

At this point, the app is a preparation phase of the Vue, preparing the functions needed for subsequent operations such as mount.

mount

The most core (tedious) operations are in mount, which includes all the core functions of Vnode, render, patch and so on. Let’s take a look at the mount call process.

  • Step 1: Call the runtime-dom mount function in index.ts.
  • Step 2: Call the mount function in the Runtime-core apiCreateApp;

The previous two steps are similar to the calls in Vue2. Call the platform-related mount first, and then call the core-related mount.

  • Step 3: Call createVNode directly; Unlike Vue2, 2 will not be called directly, but will create a watcher, use watcher call get to call, details can be seen in Vue2 source code read (7)-mount
  • Step 4: Call render to determine whether to uninstall or render;
  • Step 5: Call patch for DOM diff and render the page.

conclusion

This article is a brief start, and then the mount part will be analyzed and interpreted in detail.

The way ahead is so long without ending, yet high and low I’ll search with my will unbending.

I heard that React recently released recoil’s official state management library, which makes it easier to manage states. I look forward to Vue’s follow-up.