createApp位置
vue/src/index.ts => runtime-dom => createApp
// vue/src/index.ts
export { compileToFunction as compile }
export * from '@vue/runtime-dom'
复制代码
// runtime-dom/src/index.ts
import {
createRenderer,
createHydrationRenderer,
warn,
RootRenderFunction,
CreateAppFunction,
Renderer,
HydrationRenderer,
App,
RootHydrateFunction,
isRuntimeOnly,
DeprecationTypes,
compatUtils
} from '@vue/runtime-core'
export const createApp = ((...args) => {
const app = ensureRenderer().createApp(...args)
...
return app
}
复制代码
寻找state
ensureRenderer()
=> return createRenderer()
=> return baseCreateRenderer()
=>
return {
render,
hydrate,
createApp: createAppAPI(render, hydrate)
}
复制代码
=> createAppAPI()
打印一下
app | instance |
---|---|
state暴露在mount返回的实例,与vue2不同。app状态,data为函数(只能为Function)还未运行暴露。
mount
// mount
const vnode = createVNode(
rootComponent as ConcreteComponent,
rootProps
)
vnode.appContext = context
render(vnode, rootContainer, isSVG)
isMounted = true
app._container = rootContainer
return getExposeProxy(vnode.component!) || vnode.component!.proxy
// 这里返回的是 vnode.component!.proxy
复制代码
PublicInstanceProxyHandlers
直接看proxy handler,找到packages\runtime-core\src\componentPublicInstance.ts
export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
get({ _: instance }: ComponentRenderContext, key: string) {
...
},
set({ _: instance }: ComponentRenderContext, key: string, value: any): boolean {
...
},
has({ _: { data, setupState, accessCache, ctx, appContext, propsOptions }}: ComponentRenderContext, key: string) {
...
}
}
复制代码
试图溯源
回到第一个版本 v3.0.0-alpha.0
从readme到 Contributing Guide
Development Setup
$ yarn # install the dependencies of the project
复制代码
A high level overview of tools used:
- TypeScript as the development language
- Rollup for bundling
- Jest for unit testing
- Prettier for code formatting
oho, npm run dev
报错compiler-ssr不存在package.json文件,修复?可能还有一些问题,那还是跳版本v3.0.0-alpha.1,依然报错。那直接v3.0.0
// 总是会在这报错
const pkg = require(`../packages/${f}/package.json`)
// 为什么尤大没问题呢?是node版本问题吗?
复制代码
算了算了 继续 看v3.2.20
createApp
// packages\runtime-dom\src\index.ts
export const createApp = ((...args) => {
const app = ensureRenderer().createApp(...args)
app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
const container = normalizeContainer(containerOrSelector)
if (!container) return
container.innerHTML = ''
const proxy = mount(container, false, container instanceof SVGElement)
if (container instanceof Element) {
container.removeAttribute('v-cloak')
container.setAttribute('data-v-app', '')
}
return proxy
}
return app
}
复制代码
createVNode
// packages\runtime-core\src\apiCreateApp.ts
// createAppAPI() => return createApp()
mount() {
const vnode = createVNode(rootComponent)
return vnode.component!.proxy
}
复制代码
// packages\runtime-core\src\vnode.ts
// 判断入口
export const createVNode = (
__DEV__ ? createVNodeWithArgsTransform : _createVNode
) as typeof _createVNode
// 拦截、调整参数、最后传递 createBaseVNode
function _createVNode(
type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
props: (Data & VNodeProps) | null = null,
children: unknown = null,
patchFlag: number = 0,
dynamicProps: string[] | null = null,
isBlockNode = false
): VNode{
if (!type || type === NULL_DYNAMIC_COMPONENT){...}
if (isVNode(type)){...}
if (isClassComponent(type)) {}
return createBaseVNode(
type,
props,
children,
patchFlag,
dynamicProps,
shapeFlag,
isBlockNode,
true
)
}
复制代码
render
初始化时vnode不存在component,然后带着type进入render
//packages\runtime-core\src\renderer.ts
const render: RootRenderFunction = (vnode, container, isSVG) => {
patch(container._vnode || null, vnode, container, null, null, null, isSVG)
flushPostFlushCbs()
container._vnode = vnode
}
复制代码
patch
patch => processComponent => mountComponent => setupRenderEffect
// packages\runtime-core\src\renderer.ts
const effect = new ReactiveEffect(
componentUpdateFn,
() => queueJob(instance.update),
instance.scope // track it in component's effect scope
)
复制代码
// packages\reactivity\src\effect.ts
export class ReactiveEffect<T = any> {
active = true
deps: Dep[] = []
// can be attached after creation
computed?: boolean
allowRecurse?: boolean
onStop?: () => void
constructor(
public fn: () => T,
public scheduler: EffectScheduler | null = null,
scope?: EffectScope | null
) {
recordEffectScope(this, scope)
}
run() {}
stop() {}
}
复制代码
effect
最终将函数 componentUpdateFn 传递给 effect ,再进入track循环