Vue源码分析--vm.$mount()
Vue源码分析–vm.$mount(el)
将Vue对象挂载到指定页面元素上,下面是一些使用时的注意点
-
new Vue(options)时会根据模板生成一个vnode对象,再以vnode生成一个Element对象 new Vue(options)时,如果存在options.el,则会用生成的Element对象替换掉页面上的el 如果不存在options.el,则需手动挂载 vm.$mount(el) 如果已挂载el,则无法挂载其他el 如果new Vue(options)时不存在模板,则会以手动挂载对象 vm.$mount(el)中的el为template
然后是源码分析,我把那些异常处理相关的代码去掉了
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean // 一直没弄明白这个参数是干嘛的
): Component {
// 如果当前环境是浏览器环境,获取el节点
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
query(el)
根据传入的el元素,生成对应的Element对象
/**
* 如果el传Element元素,直接返回
* 否则返回 document.querySelector(el) 或者 document.createElement(div)
*/
export function query (el: string | Element): Element {
if (typeof el === string) {
const selected = document.querySelector(el)
if (!selected) {
return document.createElement(div)
}
return selected
} else {
return el
}
}
mountComponent(vm, el, hydrating)
vm.$mount中的核心方法,绑定更新方法,执行生命周期
export function mountComponent (
vm: Component,
el: ?Element,
hydrating?: boolean
): Component {
// 将传入的 el 赋值给 vm.$el
vm.$el = el
if (!vm.$options.render) {
vm.$options.render = createEmptyVNode
}
// 执行生命周期 beforeMount 回调,以及 hook:beforeMount,后面同理
callHook(vm, beforeMount)
let updateComponent = () => {
// vm._render() 创建并返回 VNode
// vm._update() 接受 VNode 将其转为真实节点,并替换 vm.$el
// 后续再分析 vm._render 与 vm._update 这两个方法
vm._update(vm._render(), hydrating)
}
// 监控 执行updateComponent()时 所依赖的属性;如果有变化,执行 updateComponent()
new Watcher(vm, updateComponent, noop, {
// 执行 updateComponent() 前,执行before
before () {
// new Watcher()时,也会执行一遍updateComponent(),
// 所以如果没有执行过 mounted 生命周期,就没有 beforeUpdate
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, beforeUpdate)
}
}
// 为true时,赋值 this._watcher = 当前new 出来的这个实例
// 为$forceUpdate做准备
}, true)
hydrating = false
// 如果当前vm没有虚拟节点,执行mounted生命周期
if (vm.$vnode == null) {
vm._isMounted = true
callHook(vm, mounted)
}
return vm
}
