# 编译器
# complieToFunctions
- 执行编译函数,得到编译结果
- 将编译界定符得到的字符串代码通过 new Function(codeStr) 转换成可执行的函数
- 缓存编译结果
export function compileToFunctions(
template: string,
options?: CompilerOptions,
vm?: Component
): CompiledFunctionResult {
options = extend({}, options)
// 日志
const warn = options.warn || baseWarn
delete options.warn
if (process.env.NODE_ENV !== 'production') {
// 监测CSP限制
try {
new Function('return 1')
} catch (e) {
if (e.toString().match(/unsafe-eval|CSP/)) {
// 模板编译器不能工作在CSP不安全的环境
}
}
}
// 如果有缓存,则跳过编译,直接从缓存中获取上次编译的结果
const key = options.delimiters
? String(options.delimiters) + template
: template
if (cache[key]) {
return cache[key]
}
// 执行编译函数,得到编译结果
const compiled = compile(template, options)
// 编译期间产生的error和tip,分别输出到控制台
if (process.env.NODE_ENV !== 'production') {
if (compiled.errors && compiled.errors.length) {
if (options.outputSourceRange) {
compiled.errors.forEach(e => {
warn(e)
})
}
} else {
warn()
}
if (compiled.tips && compiled.tips.length) {
if (options.outputSourceRange) {
compiled.tips.forEach(e => tip(e.msg, vm))
} else {
compiled.tips.forEach(msg => tip(msg, vm))
}
}
}
// 转换编译得到的字符串代码为幻术
const res = {}
const fnGenErrors = []
res.render = createFunction(compiled.render, fnGenErrors)
res.staticRenderFns = compiled.staticRenderFns.map(code => {
return createFunction(code, fnGenErrors)
})
return (cache[key] = res)
}
processElement
- 处理元素节点的key、ref、插槽、自闭和的 slot 标签、 动态组件...
- 然后再 el 对象上添加如下属性 el.key, el.ref,...
export function processElement(
element: ASTElement,
options: ComplierOptions
) {
// el.key = val
processKey(element)
// 确定 element 是否需要进行 genData 处理。 > 4.1 生成渲染函数
element.plain = (
!element.key &&
!element.scopedSlots &&
!element.attrsList.length
)
// el.ref = val, el.refInFor = boolean
processRef(element)
// 处理作为插槽传递给组件的内容,得到 插槽名称、是否为动态插槽、作用域插槽,以及插槽中的所有子元素
processSlotContent(element)
// 处理自闭合的 slot 标签,得到插槽名称 el.slotName = xx
processSlotOutlet(element)
// 处理动态组件 得到 el.component = compName
processComponent(element)
// 省略代码 处理各个平台的 tranformNode 方法
// 处理元素上的所有属性
// v-bin指令变为 el.attrs 或者 el.dynamicAttrs = [{ name, value, start, end, dynamic }, ...]
// v-on变为 el.events或者el.nativeEvents = { name: [{ value, start, end, modifiers,... }] }
// 其他指令: el.directives = [{name, rawName, ....}]
// 原生属性 el.attrs = [{ name, value }] 或者使用的 props el.props = [[ name, value }]
processAttrs(element)
return element
}