vue 模板編譯之源碼流程

行文介紹

本文主要介紹vue中template compile的主體思路和源碼流程。vue

適合想要梳理模板編譯對應的源碼函數調用流程的童鞋。爲你們濾清思路。git

具體的分析請查看文末參考連接。github

主體思路

三步走:

  1. 將模板解析爲AST。parseparse使用正則等方式解析template模板中的指令,class,style等數據,造成AST
  2. 優化AST。optimize主要做用是標記static靜態節點,後面當update更新界面時,會有diff的過程,會直接跳過靜態節點,從而減小比較過程,優化patch性能。
  3. 將AST轉換爲render函數。generate。將AST轉換爲render function字符串,獲得結果是render字符串以及staticRenderFns字符串。

源碼函數調用流程

整個源碼很是貼近函數式編程,可是也致使閱讀理解的成本很高,基本都是高階函數,函數被傳入傳出的,很容易被繞暈。web

可是抓住核心就行,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... 【這篇文章不錯,推薦閱讀】函數

相關文章
相關標籤/搜索