app.mount('#app')的大致流程
app.mount实际调用的函数
- 会先通过document.querySelector获取container节点。如果该节点不存在,直接返回。
- 清空container的innerHTML
- 调用mount函数。
- 如果container是Element的实例,删除v-cloak属性,以及添加data-v-app属性。
app.mount = (containerOrSelector) => {
const container = normalizeContainer(containerOrSelector)
if (!container) return
const component = app._component
if (!isFunction(component) && !component.render && !component.template) {
component.template = container.innerHTML
if (__COMPAT__ && __DEV__) {
for (let i = 0; i < container.attributes.length; i++) {
const attr = container.attributes[i]
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
compatUtils.warnDeprecation(
DeprecationTypes.GLOBAL_MOUNT_CONTAINER,
null
)
break
}
}
}
}
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
}
mount函数
- mount函数会根据isMounted这个变量判断是否已经被挂载过。
- 没有被挂载过:调用createVnode创建vnode。调用render函数将vnode和container作为参数传递进去。
- 如果被挂载过并且是在开发环境中,发出警告。
function mount(rootContainer, isHydrate, isSVG) {
if (!isMounted) {
const vnode = createVNode( rootComponent, rootProps)
vnode.appContext = context
if (isHydrate && hydrate) {
hydrate(vnode as VNode<Node, Element>, rootContainer as any)
} else {
render(vnode, rootContainer, isSVG)
}
isMounted = true
app._container = rootContainer
;(rootContainer).__vue_app__ = app
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
app._instance = vnode.component
devtoolsInitApp(app, version)
}
return getExposeProxy(vnode.component!) || vnode.component!.proxy
} else if (__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)\``
)
}
},
mount中调用的render函数
- 如果vnode为null并且container._vnode属性不为undefined,那么unmount该节点。
- 如果vnode不为null进行patch。
const render = (vnode, container, isSVG) => {
if (vnode == null) {
if (container._vnode) {
unmount(container._vnode, null, null, true)
}
} else {
patch(container._vnode || null, vnode, container, null, null, null, isSVG)
}
flushPostFlushCbs()
container._vnode = vnode
}
vue源码的其他阅读笔记