exportfunction createAppAPI<HostElement>(
render: RootRenderFunction,
hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement>{// createApp 将若干属性和方法挂载在 app 这个变量中,最后并返回 app。returnfunctioncreateApp(rootComponent, rootProps =null){// 对传递进来的第二个参数,也就是rootProps进行校验if(rootProps !=null&&!isObject(rootProps)){
__DEV__ &&warn(`root props passed to app.mount() must be an object.`)
rootProps =null}// 创建默认APP配置,调用createAppContext创建appContext对象,赋值给contextconst context =createAppContext()// 创建变量installedPlugins(Set类型),存储已经安装过的插件const installedPlugins =newSet()// isMounted设为falselet isMounted =false// 创建app,挂载属性和函数 const app: App =(context.app ={
_uid: uid++,
_component: rootComponent as ConcreteComponent,
_props: rootProps,
_container:null,
_context: context,
_instance:null,
version,getconfig(){return context.config
},setconfig(v){if(__DEV__){warn(`app.config cannot be replaced. Modify individual options instead.`)}},use(plugin: Plugin,...options: any[]){if(installedPlugins.has(plugin)){
__DEV__ &&warn(`Plugin has already been applied to target app.`)}elseif(plugin &&isFunction(plugin.install)){
installedPlugins.add(plugin)
plugin.install(app,...options)}elseif(isFunction(plugin)){
installedPlugins.add(plugin)plugin(app,...options)}elseif(__DEV__){warn(`A plugin must either be a function or an object with an "install" `+`function.`)}// 返回app,此时的app属于Vue的一个准备阶段,为后面的mount等操作准备好了所需要使用到的函数。return app
},mixin(mixin: ComponentOptions){if(__FEATURE_OPTIONS_API__){if(!context.mixins.includes(mixin)){
context.mixins.push(mixin)}elseif(__DEV__){warn('Mixin has already been applied to target app'+(mixin.name ?`: ${mixin.name}`:''))}}elseif(__DEV__){warn('Mixins are only available in builds supporting Options API')}return app
},component(name: string, component?: Component): any {if(__DEV__){validateComponentName(name, context.config)}if(!component){return context.components[name]}if(__DEV__ && context.components[name]){warn(`Component "${name}" has already been registered in target app.`)}
context.components[name]= component
return app
},directive(name: string, directive?: Directive){if(__DEV__){validateDirectiveName(name)}if(!directive){return context.directives[name]as any
}if(__DEV__ && context.directives[name]){warn(`Directive "${name}" has already been registered in target app.`)}
context.directives[name]= directive
return app
},// mount(
rootContainer: HostElement,
isHydrate?: boolean,
isSVG?: boolean
): any {if(!isMounted){const vnode =createVNode(
rootComponent as ConcreteComponent,
rootProps
)// store app context on the root VNode.// this will be set on the root instance on initial mount.
vnode.appContext = context
// HMR root reloadif(__DEV__){
context.reload=()=>{render(cloneVNode(vnode), rootContainer, isSVG)}}if(isHydrate && hydrate){hydrate(vnode as VNode<Node, Element>, rootContainer as any)}else{render(vnode, rootContainer, isSVG)}
isMounted =true
app._container = rootContainer
// for devtools and telemetry;(rootContainer as any).__vue_app__ = app
if(__DEV__ || __FEATURE_PROD_DEVTOOLS__){
app._instance = vnode.component
devtoolsInitApp(app, version)}return vnode.component!.proxy
}elseif(__DEV__){warn(`App has already been mounted.\n`+`If you want to remount the same app, move your app creation logic `+`into a factory function and create fresh app instances for each `+`mount - e.g. \`const createMyApp = () => createApp(App)\``)}},unmount(){if(isMounted){render(null, app._container)if(__DEV__ || __FEATURE_PROD_DEVTOOLS__){
app._instance =nulldevtoolsUnmountApp(app)}delete app._container.__vue_app__
}elseif(__DEV__){warn(`Cannot unmount an app that is not mounted.`)}},provide(key, value){if(__DEV__ &&(key as string | symbol)in context.provides){warn(`App already provides property with key "${String(key)}". `+`It will be overwritten with the new value.`)}// TypeScript doesn't allow symbols as index type// https://github.com/Microsoft/TypeScript/issues/24587
context.provides[key as string]= value
return app
}})if(__COMPAT__){installAppCompatProperties(app, context, render)}return app
}}