vue中模板编译compiler源码详解
生活随笔
收集整理的這篇文章主要介紹了
vue中模板编译compiler源码详解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
vue編譯模板過程;
<div><h1>這是compiler</h1> <p v-if="message">{{ message }}</p><p v-else>No messageq.</p> </div>編譯成render函數如下:
function anonymous( ) {with(this){return _c('div',[_c('h1',[_v("這是compiler")]),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No messageq.")])])} }vue compiler入口:
// platforms/web/entry-runtime-with-compiler.jsVue.prototype.$mount = function (el?: string | Element,hydrating?: boolean ): Component {el = el && query(el)// ...const options = this.$options// 如果是render則走render 若是template、el則需要編程renderif (!options.render) {let template = options.templateif (template) {if (typeof template === 'string') {if (template.charAt(0) === '#') {template = idToTemplate(template)/* istanbul ignore if */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 {if (process.env.NODE_ENV !== 'production') {warn('invalid template option:' + template, this)}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 = renderoptions.staticRenderFns = staticRenderFns}}// ...return mount.call(this, el, hydrating) }// 調用createCompilerCreator, 拿到compileToFunctions方法
createCompilerCreator(function baseCompile (template: string,options: CompilerOptions ): CompiledResult {const ast = parse(template.trim(), options)if (options.optimize !== false) {optimize(ast, options)}const code = generate(ast, options)return {ast,render: code.render,staticRenderFns: code.staticRenderFns} })// createCompilerCreator
function createCompilerCreator (baseCompile: Function): Function {return function createCompiler (baseOptions: CompilerOptions) {function compile (template: string,options?: CompilerOptions): CompiledResult {const finalOptions = Object.create(baseOptions)const errors = []const tips = []let warn = (msg, range, tip) => {(tip ? tips : errors).push(msg)}if (options) {if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {// $flow-disable-lineconst leadingSpaceLength = template.match(/^\s*/)[0].lengthwarn = (msg, range, tip) => {const data: WarningMessage = { msg }if (range) {if (range.start != null) {data.start = range.start + leadingSpaceLength}if (range.end != null) {data.end = range.end + leadingSpaceLength}}(tip ? tips : errors).push(data)}}// merge custom modulesif (options.modules) {finalOptions.modules =(baseOptions.modules || []).concat(options.modules)}// merge custom directivesif (options.directives) {finalOptions.directives = extend(Object.create(baseOptions.directives || null),options.directives)}// copy other optionsfor (const key in options) {if (key !== 'modules' && key !== 'directives') {finalOptions[key] = options[key]}}}finalOptions.warn = warnconst compiled = baseCompile(template.trim(), finalOptions)if (process.env.NODE_ENV !== 'production') {detectErrors(compiled.ast, warn)}compiled.errors = errorscompiled.tips = tipsreturn compiled}return {compile,compileToFunctions: createCompileToFunctionFn(compile)}} }// createCompileToFunctionFn
function createCompileToFunctionFn (compile: Function): Function {const cache = Object.create(null)return function compileToFunctions (template: string,options?: CompilerOptions,vm?: Component): CompiledFunctionResult {options = extend({}, options)const warn = options.warn || baseWarndelete options.warn/* istanbul ignore if */if (process.env.NODE_ENV !== 'production') {// detect possible CSP restrictiontry {new Function('return 1')} catch (e) {if (e.toString().match(/unsafe-eval|CSP/)) {warn('It seems you are using the standalone build of Vue.js in an ' +'environment with Content Security Policy that prohibits unsafe-eval. ' +'The template compiler cannot work in this environment. Consider ' +'relaxing the policy to allow unsafe-eval or pre-compiling your ' +'templates into render functions.')}}}// check cacheconst key = options.delimiters? String(options.delimiters) + template: templateif (cache[key]) {return cache[key]}// compileconst compiled = compile(template, options)// check compilation errors/tipsif (process.env.NODE_ENV !== 'production') {if (compiled.errors && compiled.errors.length) {if (options.outputSourceRange) {compiled.errors.forEach(e => {warn(`Error compiling template:\n\n${e.msg}\n\n` +generateCodeFrame(template, e.start, e.end),vm)})} else {warn(`Error compiling template:\n\n${template}\n\n` +compiled.errors.map(e => `- ${e}`).join('\n') + '\n',vm)}}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))}}}// turn code into functionsconst res = {}const fnGenErrors = []res.render = createFunction(compiled.render, fnGenErrors)res.staticRenderFns = compiled.staticRenderFns.map(code => {return createFunction(code, fnGenErrors)})// check function generation errors.// this should only happen if there is a bug in the compiler itself.// mostly for codegen development use/* istanbul ignore if */if (process.env.NODE_ENV !== 'production') {if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {warn(`Failed to generate render function:\n\n` +fnGenErrors.map(({ err, code }) => `${err.toString()} in\n\n${code}\n`).join('\n'),vm)}}return (cache[key] = res)} }總結
以上是生活随笔為你收集整理的vue中模板编译compiler源码详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: svgsprite的svg-sprite
- 下一篇: nodejs express使用node