初始化渲染
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
createApp
export const createApp = ((...args) => {
// 初始化 app 对象
const app = ensureRenderer().createApp(...args)
if (__DEV__) {
// 检查是否原生标签
injectNativeTagCheck(app)
// 检查是否自定义标签
injectCompilerOptionsCheck(app)
}
// ...
return app
}) as CreateAppFunction<Element>
从上面代码中可以看到 app 对象是通过 ensureRenderer 函数返回的 createApp 函数执行得出。
function ensureRenderer() {
return (
renderer || (renderer = createRenderer<Node, Element | ShadowRoot>(rendererOptions))
)
}
rendererOptions 对象主要封装了对原生 DOM 对象操作的相关 API,比如:setAttribute、insertBefore、createElement 等。将其作为参数传入 createRenderer 函数中。
export function createRenderer<
HostNode = RendererNode,
HostElement = RendererElement
>(options: RendererOptions<HostNode, HostElement>) {
// 实质上是执行 baseCreateRenderer 函数
// 入参 options 为 rendererOptions 对象
return baseCreateRenderer<HostNode, HostElement>(options)
}
function baseCreateRenderer(
options: RendererOptions,
createHydrationFns?: typeof createHydrationFunctions
) {
const {
insert: hostInsert,
remove: hostRemove,
// ...
cloneNode: hostCloneNode,
insertStaticContent: hostInsertStaticContent
} = options
// ...
return {
// 渲染函数
render,
// SSR
hydrate,
// creteApp 本体
createApp: createAppAPI(render, hydrate)
}
}
createApp 即为 createAppAPI(render, hydrate) 返回的函数。baseCreateRenderer 函数本身就是一个大闭包,并且采用函数柯里化,很好的将方法、对象进行了私有化和缓存。
回到上面说的 const app = ensureRenderer().createApp(...args) 这换代码,实际等价于 createAppAPI(render, hydrate)(...args)
export function createAppAPI<HostElement>(
render: RootRenderFunction,
hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement> {
return function createApp(rootComponent, rootProps = null) {
// ...
const context = createAppContext()
// ...
const app: App = (context.app = {
_uid: uid++,
_component: rootComponent as ConcreteComponent,
_props: rootProps,
_container: null,
_context: context,
_instance: null,
version,
get config() {/* ... */},
set config(v) {/* ... */},
use(plugin: Plugin, ...options: any[]) {/* ... */},
mixin(mixin: ComponentOptions) {/* ... */},
component(name: string, component?: Component): any {/* ... */},
mount(
rootContainer: HostElement,
isHydrate?: boolean,
isSVG?: boolean
): any {/* ... */},
unmount() {/* ... */},
provide(key, value) {/* ... */}
})
// ...
// app 对象本体
return app
}
从上面的代码中可以看得出执行 const app = ensureRenderer().createApp(...args) 后,返回的 app 对象的具体属性及方法