返回
揭开Vue源码的奥秘:Vue实例挂载的实现
前端
2023-09-14 07:47:43
Vue 实例挂载的实现
在上一节中,我们看到会调用 vm.$mount(vm.$options.el);
来挂载实例,那么 $mount
是什么?$mount
方法在多个文件中都有定义,分别对应着不同的挂载场景。
src/core/instance/index.js
Vue.prototype.$mount = function (
el?: string | Element | Component,
hydrating?: boolean
) {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
这是 Vue.prototype.$mount
方法的定义,它接受两个参数:el
和 hydrating
。
el
是需要挂载的元素。它可以是字符串选择器、DOM 元素或组件。hydrating
是一个布尔值,表示是否正在进行服务端渲染。
$mount
方法首先会检查 el
是否存在。如果 el
不存在,则直接返回。否则,它会调用 mountComponent
方法来挂载组件。
src/core/instance/lifecycle.js
export function mountComponent (
vm: Component,
el: Element | null,
hydrating?: boolean
): Component {
vm.$el = el
if (!vm.$options.render) {
vm.$options.render = createEmptyVNode
}
callHook(vm, 'beforeMount')
let updateComponent
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
updateComponent = () => {
const name = vm._name
mark('vue-perf-start:mount')
const vnode = vm._render()
mark('vue-perf-end:mount')
measure(`vue-perf:mount: ${name}`, 'vue-perf-start:mount', 'vue-perf-end:mount')
callHook(vm, 'mounted')
}
} else {
updateComponent = () => {
callHook(vm, 'mounted')
}
}
vm._update(vm._render(), hydrating)
// queue the update, so that the mounted hook is called
// after the first update.
nextTick(updateComponent)
return vm
}
mountComponent
方法首先会设置 vm.$el
为 el
。然后,它会检查 vm.$options.render
是否存在。如果不存在,则会创建一个空的虚拟节点。
接下来,它会调用 callHook(vm, 'beforeMount')
来触发 beforeMount
生命周期钩子。
然后,它会创建一个 updateComponent
函数。这个函数将在组件更新时被调用。
接下来,它会调用 vm._update(vm._render(), hydrating)
来更新组件。
最后,它会调用 nextTick(updateComponent)
来将 updateComponent
函数加入到下一个事件循环中。这确保了 mounted
生命周期钩子在第一次更新之后被调用。
总结
Vue 实例挂载的实现是一个复杂的过程,涉及到多个文件和函数。它需要先找到挂载的元素,然后创建虚拟节点,再调用一系列生命周期钩子,最后更新组件。