Vue3.x createApp

Vue3


# createApp

# 使用

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
1
2
3
4

# 定义

let renderer
function ensureRenderer() {
  return renderer || (renderer = createRenderer(rendererOptions))
}

const createApp = (...args) => {
  const app = ensureRenderer().createApp(...args)
  // ...
  const { mount } = app
  // mount 方法被重写了
  app.mount = (containerOrSelector) => {
    // ...
  }
  return app
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# createRenderer

function createRenderer(options) {
  return baseCreateRenderer(options)
}

function baseCreateRenderer(options, createHydrationFns) {
  // ...

  const render = (vnode, container, isSVG) => {
    // vnode 不存在
    if (vnode == null) {
      if (container._vnode) {
        unmount(container._vnode, null, null, true)
      }
    } else {
      patch(container._vnode || null, vnode, container, null, null, null, isSVG)
    }
    flushPostFlushCbs()
    container._vnode = vnode
  }

  return {
    render,
    hydrate,
    createApp: createAppAPI(render, hydrate),
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# createAppAPI

let uid = 0
function createAppContext() {
  return {
    app: null,
    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(),
  }
}
function createAppAPI(render, hydrate) {
  return function createApp(rootComponent, rootProps = null) {
    if (rootProps != null && !isObject(rootProps)) {
      warn$1(`root props passed to app.mount() must be an object.`)
      rootProps = null
    }
    const context = createAppContext()
    const installedPlugins = new Set()
    let isMounted = false
    const app = (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) {
        // ...
        return app
      },
      mixin(mixin) {
        // ...
        return app
      },
      component(name, component) {
        // ...
        return app
      },
      directive(name, directive) {
        // ...
        return app
      },
      mount(rootContainer, isHydrate, isSVG) {
        // ...
      },
      unmount() {
        // ...
      },
      provide(key, value) {
        // ...
        return app
      },
    })
    return app
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

可以看到 Vue3 采用了一种无 new 构造的方式创造了一个 app 应用实例。这也使得在 vue2 中使用 vue.prototype.xxx 来定义所有组件实例都能访问的方法和属性的方式在 vue3 中将不再支持,

  • vue2
import axios from 'axios'

Vue.prototype.$axios = axios
1
2
3
  • vue3
import axios from 'axios'

const app = createApp({})

app.config.globalProperties.$axios = axios

// 在组件中可以通过this访问

this.$axios(/*...*/)
1
2
3
4
5
6
7
8
9

并且像之前在 Vue 构造器上定义的许多静态方法,现在也都变成了通过 app 实例来调用

app.use()
app.component()
app.mixin()
app.directive()
app.mixin()
1
2
3
4
5
Last Updated: 10/21/2024, 4:15:17 PM