乐趣区

vue-模板编译之源码流程

行文介绍

本文主要介绍 vue 中 template compile 的主体思路和源码流程。

适合想要梳理模板编译对应的源码函数调用流程的童鞋。为大家滤清思路。

具体的分析请查看文末参考链接。

主体思路

三步走:

  1. 将模板解析为 AST。parseparse 使用正则等方式解析 template 模板中的指令,class,style 等数据,形成 AST
  2. 优化 AST。optimize主要作用是标记 static 静态节点,后面当 update 更新界面时,会有 diff 的过程,会直接跳过静态节点,从而减少比较过程,优化 patch 性能。
  3. 将 AST 转换为 render 函数。generate。将 AST 转换为 render function 字符串,得到结果是 render 字符串以及 staticRenderFns 字符串。

源码函数调用流程

整个源码非常贴近函数式编程,但是也导致阅读理解的成本很高,基本都是高阶函数,函数被传入传出的,很容易被绕晕。

但是抓住核心就行,createCompiler 函数。

核心函数

createCompiler

简要流程

compileToFunctions
<==
createCompiler
<==
createCompilerCreator
<==
createCompileToFunctionFn
<==
createFunction

详细流程

// src/platforms/web/entry-runtime-with-compiler.js
const {render, staticRenderFns} = compileToFunctions(template, {
    outputSourceRange: process.env.NODE_ENV !== 'production',
    shouldDecodeNewlines,
    shouldDecodeNewlinesForHref,
    delimiters: options.delimiters,
    comments: options.comments
}, this)


// src/platforms/web/compiler/index.js
const {compile, compileToFunctions} = createCompiler(baseOptions)


// src/compiler/index.js
export const createCompiler = createCompilerCreator(function baseCompile (
  template: string,
  options: CompilerOptions
): CompiledResult {
  // 三步走 parse optimize generate
  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
  }
})


// src/compiler/create-compiler.js
export function createCompilerCreator (baseCompile: Function): Function {return function createCompiler (baseOptions: CompilerOptions) {
    function compile (
      template: string,
      options?: CompilerOptions
    ): CompiledResult {const compiled = baseCompile(template.trim(), finalOptions)
        ...
        return compiled
        
    }
    
    return {
      compile,
      // 真实使用的是这个函数 compileToFunctions
      compileToFunctions: createCompileToFunctionFn(compile)
    }
  }
}

// src/compiler/to-function.js
export function createCompileToFunctionFn (compile: Function): Function {

    return function compileToFunctions (
        template: string,
        options?: CompilerOptions,
        vm?: Component
    ): CompiledFunctionResult {
        
         // compile
        const compiled = compile(template, options)
    
        res.render = createFunction(compiled.render, fnGenErrors)
        
        return (cache[key] = res)
    }
}


// src/compiler/to-function.js
function createFunction (code, errors) {
  try {return new Function(code)
  } catch (err) {errors.push({ err, code})
    return noop
  }
}

参考链接

https://github.com/answershut…【这篇文章不错,推荐阅读】

退出移动版