一首歌的时间说说vue的模板编译

62 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8月更文挑战」的第12天,点击查看活动详情

什么是模板编译

vue把用户在<template></template>标签中写的类似html的内容进行编译,找出原生html的内容和非原生html的内容,经过一系列逻辑处理生成render函数,render会将这些内容生成对应的VNode,再通过patch过程得到要渲染视图中的VNode,然后根据VNode创建真实dom节点,插入视图中,完成视图的渲染更新。 因为有了模板编译,才有了虚拟DOM,才有了后续的视图更新

模板编译内部流程

1.把html代码转成ast语法树。(通过正则加循环,正则来匹配开始标签,结束标签,处理文本,以及标签名称。解析指令,class,style)
2.优化静态节点
3.根据ast生成render函数

// 源码位置: /src/complier/index.js

export const createCompiler = createCompilerCreator(function baseCompile (
  template: string,
  options: CompilerOptions
): CompiledResult {
  // 模板解析阶段:用正则等方式解析 template 模板中的指令、class、style等数据,形成AST
  const ast = parse(template.trim(), options)
  if (options.optimize !== false) {
    // 优化阶段:遍历AST,找出其中的静态节点,并打上标记;
    optimize(ast, options)
  }
  // 代码生成阶段:将AST转换成渲染函数;
  const code = generate(ast, options)
  return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
})

模版解析

// 代码位置:/src/complier/parser/index.js

/**
 * Convert HTML string to AST.
 */
export function parse(template, options) {
   // ...
  parseHTML(template, {
    warn,
    expectHTML: options.expectHTML,
    isUnaryTag: options.isUnaryTag,
    canBeLeftOpenTag: options.canBeLeftOpenTag,
    shouldDecodeNewlines: options.shouldDecodeNewlines,
    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
    shouldKeepComment: options.comments,
    start (tag, attrs, unary) {

    },
    end () {

    },
    chars (text: string) {

    },
    comment (text: string) {

    }
  })
  return root
}

4.16462ada.png 通过正则等方式将有效信息提取出来,将解析内容分为HTML解析器,文本解析器和过滤器解析器。parse 函数就是解析器的主函数,在parse 函数内调用了parseHTML 函数,对模板字符串进行解析,在parseHTML 函数解析模板字符串的过程中,如果遇到文本信息,就会调用文本解析器parseText函数进行文本解析;如果遇到文本中包含过滤器,就会调用过滤器解析器parseFilters函数进行解析。