Vue3源码学习笔记—— Vue.createApp(App) 和 app.mount(“#app“)(二)
本篇文章对 Vue.createApp(App)做了什么进行了简单分析,以上篇文章的 demo 为例。
前情回顾
本篇文章对 Vue.createApp(App) 做了什么进行了简单分析,以上篇文章的 demo 为例。
戳链接回顾上篇文章
Vue3源码学习笔记—— Vue.createApp(App) 和 app.mount(“#app”)(一) - 掘金 (juejin.cn)
Vue.createApp(App) 做了什么
createApp 函数
位置:/packages/runtime-dom/src/index.ts
首先,我们定义了一个根组件 App ,并将 App 传入 Vue.createApp() ,而 createApp 存在于 runtime-dom (运行时)中,代码如下。
export const createApp = ((...args) => {
// 1.创建app对象
/*
(1)ensureRenderer()是一个完整的渲染器Renderer,和渲染相关的代码都在这里
(2)传入的参数用于调用ensureRenderer().createApp(...args),该函数最终返回一个app对象并赋值给新创建的app对象
*/
const app = ensureRenderer().createApp(...args)
if (__DEV__) {
injectNativeTagCheck(app)
injectCompilerOptionsCheck(app)
}
const { mount } = app
app.mount = (containerOrSelector: Element | ShadowRoot | string): any => { ... }
return app
}) as CreateAppFunction<Element>
可见,传入的参数并没有在函数中被使用,而是用于调用ensureRenderer().createApp(),该函数最终返回一个app对象并赋值给新创建的app对象。
ensureRenderer 函数
位置:/packages/runtime-dom/src/index.ts
该函数判断已定义的 renderer 渲染器有没有值,如果已经有渲染器就直接返回,如果没有渲染器,那么调用 createRenderer 创建渲染器。
let renderer: Renderer<Element | ShadowRoot> | HydrationRenderer
let enabledHydration = false
function ensureRenderer() {
// 已有渲染器 -> 直接返回
// 没有渲染器 -> 调用createRenderer创建渲染器
return (
renderer ||
(renderer = createRenderer<Node, Element | ShadowRoot>(rendererOptions))
)
}
createRenderer 函数
位置:/packages/runtime-core/src/renderer.ts
该函数返回调用了 baseCreateRenderer 函数。
export function createRenderer<
HostNode = RendererNode,
HostElement = RendererElement
>(options: RendererOptions<HostNode, HostElement>) {
return baseCreateRenderer<HostNode, HostElement>(options)
}
baseCreateRenderer 函数
位置:/packages/runtime-core/src/renderer.ts
// baseCreateRenderer函数进行了函数重载,真正实现是在这个位置的
function baseCreateRenderer(
options: RendererOptions,
createHydrationFns?: typeof createHydrationFunctions
): any {
// 由于篇幅限制,此处省略2000多行......
return {
render,
hydrate,
// 此处采用了柯里化,将render函数及其他相关参数全部传入createAppAPI函数中
createApp: createAppAPI(render, hydrate)
}
}
现在我们回到 createApp 函数中,可以发现,ensureRenderer().createApp(...args)
最终调用的是 createAppAPI()
函数,如图所示。
createAppAPI 函数
位置:/packages/runtime-core/src/apiCreateApp.ts
该函数通过返回调用 createApp 函数,最终返回了一个app对象。
export function createAppAPI<HostElement>(
render: RootRenderFunction,
hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement> {
return function createApp(rootComponent, rootProps = null) {
if (!isFunction(rootComponent)) {
rootComponent = { ...rootComponent }
}
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
// 定义了一个app对象,用以返回
const app: App = (context.app = {
_uid: uid++,
_component: rootComponent as ConcreteComponent,
_props: rootProps,
_container: null,
_context: context,
_instance: null,
version,
get config() {
return context.config
},
// set是不允许赋值的,赋值后会报错
set config(v) {
if (__DEV__) {
warn(
`app.config cannot be replaced. Modify individual options instead.`
)
}
},
use() { ... return app },
mixin() { ... return app },
component() { ... return app },
directive() { ... return app },
mount() { ... },
unmount() { ... },
provide(key, value) { ... return app }
})
if (__COMPAT__) {
installAppCompatProperties(app, context, render)
}
return app
}
}
总结
以上就是对 Vue.createApp(App) 的阅读分析,下篇文章我们将对 demo 中 app.mount("#app")
的实现流程进行分析。
戳链接直达
Vue3源码学习笔记—— Vue.createApp(App) 和 app.mount(“#app”)(三) - 掘金 (juejin.cn)
更多推荐
所有评论(0)