Vue 源码解析(1)
Vue源码分析-CreateApp
官网解释
创建一个应用实例
类型
1
function createApp(rootComponent: Component, rootProps?: object): App
详细信息
第一个参数是根组件。第二个参数可选,它是要传递给根组件的 props。
示例
可以直接内联根组件:
1
2
3
4
5import { createApp } from 'vue'
const app = createApp({
/* root component options */
})也可以使用从别处导入的组件:
1
2
3
4import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)源码位置
packages/runtime-core/src/apiCreateApp.ts
函数名
createAppAPI
mini-vue中的实现(简化版vue实现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15export function createAppAPI(render) {
return function createApp(rootComponent) {
const app = {
_component: rootComponent,
mount(rootContainer) {
console.log("基于根组件创建 vnode");
const vnode = createVNode(rootComponent);
console.log("调用 render,基于 vnode 进行开箱");
render(vnode, rootContainer);
},
};
return app;
};
}
createApp源码内函数处理
部分源码
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
27export function createAppAPI<HostElement>(
render: RootRenderFunction<HostElement>,
hydrate?: RootHydrateFunction
): CreateAppFunction<HostElement> {
if (!isFunction(rootComponent)) {
rootComponent = extend({}, rootComponent)
}
if (rootProps != null && !isObject(rootProps)) {
__DEV__ && warn(`root props passed to app.mount() must be an object.`)
rootProps = null
}
const context = createAppContext()
// ...
const app: App = (context.app = {
// ...
})
if (__COMPAT__) {
installAppCompatProperties(app, context, render)
}
return app
}创建context源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// createApp经过一些列判断之后使用createAppContext,创建了一个空的根组件对象
export function createAppContext(): AppContext {
return {
app: null as any,
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()
}
}创建完context后,给context.app赋值, 其中包含的属性及含义:
_uid
_component(createApp传入的rootComponent处理来的)
_props(createApp传入的rootProps处理来的)
_container mount传入的rootContainer
_context(context实例)
_instance (mount时创建的vnode的component)
version(Vue版本)
config
特殊处理设置getter、setter
getter 返回 context.config
setter 开发环境提示不让直接更改该属性
use 对应app.use(plugin: Plugin, …options: any[])
mixin 方法
如果支持选项式API则将传入的mixin存放到context.mixins
内部有去重处理component 同app.component()
directive 同 app.directive()
mount
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
30mount(
rootContainer: HostElement,
isHydrate?: boolean,
isSVG?: boolean
): any {
// ...
// 创建vnode
const vnode = createVNode(rootComponent, rootProps)
// store app context on the root VNode.
// this will be set on the root instance on initial mount.
// 将当前的上下文给vnode挂上
vnode.appContext = context
// ...
// 判断用那个函数渲染
if (isHydrate && hydrate) {
hydrate(vnode as VNode<Node, Element>, rootContainer as any)
} else {
render(vnode, rootContainer, isSVG)
}
app._container = rootContainer // 将mount传入的rootContainer赋值给_container
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
// 将vnode的component赋值给app的_instance
app._instance = vnode.component
devtoolsInitApp(app, version)
}
// 返回一个根组件实例
return getExposeProxy(vnode.component!) || vnode.component!.proxy
// ...
}unmount
1
2
3
4
5
6
7
8unmount() {
// ...
render(null, app._container) // 卸载应用
// ...
app._instance = null // 将_instance赋空
// ...
delete app._container.__vue_app__ // 删除__vue_app__标记
}provide
1
2
3
4
5
6
7provide(key, value) {
// ...
// 提供一个值,可以在应用中的所有后代组件中注入使用
context.provides[key as string | symbol] = value
// 返回当前实例可以链式调用
return app
}runWithContext
3.3+1
2
3
4
5
6
7
8
9
10runWithContext(fn) {
// 当前应用
currentApp = app
try {
// 执行回调函数
return fn()
} finally {
currentApp = null
}
}
app属性参考,官网地址: https://cn.vuejs.org/api/application.html
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Wang的博客!
评论
