<script src="../../dist/vue.global.js"></script>
<div id="app">
<div>vue3 compiler principle</div>
<div>{{count}}</div>
</div>
<script>
var { createApp } = Vue
var app = createApp({
data() {
return {
count: 1
}
}
})
app.mount('#app')
console.log(app._instance.render);
</script>
打印出渲染函数render
_hoisted_1
把vue3 compiler principle
给缓存起来,因为不需要处理(function anonymous(
) {
const _Vue = Vue
const { createElementVNode: _createElementVNode } = _Vue
const _hoisted_1 = /*#__PURE__*/_createElementVNode("div", null, "vue3 compiler principle", -1 /* HOISTED */)
return function render(_ctx, _cache) {
with (_ctx) {
const { createElementVNode: _createElementVNode, toDisplayString: _toDisplayString, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue
return (_openBlock(), _createElementBlock(_Fragment, null, [
_hoisted_1,
_createElementVNode("div", null, _toDisplayString(count), 1 /* TEXT */)
], 64 /* STABLE_FRAGMENT */))
}
}
})
template
编译为render
函数( js
)html
描述视图,开发效率高setupComponent
时finishComponentSetup
compile
compileToFunction
最开始备份compileToFunction
registerRuntimeCompiler(compileToFunction)
let compile
function registerRuntimeCompiler(_compile) {
compile = _compile // 在这里把compileToFunction 存到 compile
installWithProxy = i => {
if (i.render!._rc) {
i.withProxy = new Proxy(i.ctx, RuntimeCompiledPublicInstanceProxyHandlers)
}
}
}
function compileToFunction(
template
options
) {
if (!isString(template)) { // 这种的是 用户直接传入节点
if (template.nodeType) {
template = template.innerHTML
} else {
return NOOP
}
}
const key = template
const cached = compileCache[key]
if (cached) {
return cached
}
if (template[0] === '#') {
const el = document.querySelector(template)
template = el ? el.innerHTML : ``
}
const { code } = compile( // 把模板给编译一下
template,
extend(
{
hoistStatic: true
options
)
)
const render = ( // 使用new 转换上面的code为一个函数
__GLOBAL__ ? new Function(code)() : new Function('Vue', code)(runtimeDom)
)
render._rc = true
return (compileCache[key] = render)
}
执行compile就是执行备份的compileToFunction
function finishComponentSetup(
instance,
isSSR,
skipOptions
) {
Component.render = compile(template, finalCompilerOptions)
}
function compileToFunction(template,options) {
const { code } = compile( template )
}
export function compile(
template: string,
options: CompilerOptions = {}
): CodegenResult {
return baseCompile(
template,
extend({}, parserOptions, options, {
nodeTransforms: [
ignoreSideEffectTags,
...DOMNodeTransforms,
...(options.nodeTransforms || [])
],
directiveTransforms: extend(
{},
DOMDirectiveTransforms,
options.directiveTransforms || {}
),
transformHoist: __BROWSER__ ? null : stringifyStatic
})
)
}