$mount 做了什么
- 前面我们提到过,我们的 demo 在执行完
vm.$mount(vm.$options.el)
就把 hello 渲染到了页面上,那这个过程发生了什么呢 - 我们先看下
entry-runtime-with-compiler.js
,其中定义了 $mount 方法
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && query(el)
if (el === document.body || el === document.documentElement) {
return this
}
const options = this.$options
if (!options.render) {
let template = options.template
if (template) {
if (typeof template === 'string') {
if (template.charAt(0) === '#') {
template = idToTemplate(template)
if (process.env.NODE_ENV !== 'production' && !template) {
warn(
`Template element not found or is empty: ${options.template}`,
this
)
}
}
} else if (template.nodeType) {
template = template.innerHTML
} else {
return this
}
} else if (el) {
template = getOuterHTML(el)
}
if (template) {
const { render, staticRenderFns } = compileToFunctions(template, {
outputSourceRange: process.env.NODE_ENV !== 'production',
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
options.render = render
options.staticRenderFns = staticRenderFns
}
}
return mount.call(this, el, hydrating)
}
- 首先它
query $options.el
,通过 query 函数我们可以发现这一步实际上就是获取真实的DOM元素
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
}
}
- 接着会判断获取的真实 dom元素是否为 body 或 documentElement
- 接下来会判断 options.render 是否有存在,我们的 demo 里并没有写 render,因此继续看里面的逻辑
- 没有 render 它会判断 options.template 是否存在,如果不存在
template = getOuterHTML(el)
,即获取 el 的 outerHTML
function getOuterHTML (el: Element): string {
if (el.outerHTML) {
return el.outerHTML
} else {
const container = document.createElement('div')
container.appendChild(el.cloneNode(true))
return container.innerHTML
}
}
然后通过
compileToFunctions
将 template 转化为 render 函数,options.render = render
再调用
mount.call(this, el, hydrating)
,这里的 mount 函数是什么呢,在代码第一行里const mount = Vue.prototype.$mount
,所以此处我们调用的是之前原型对象上的 $mount 函数,这个函数的做了什么我们会在下一篇中进行分析
调试 demo
-
执行 $mount 出 debugger
-
拿到 template
-
template 转化为 render 函数