返回

不用正则表达式,用javascript从零写一个模板引擎(一)

前端

前言

模板引擎的作用就是将模板渲染成html,html = render(template,data),常见的js模板引擎有Pug,Nunjucks,Mustache等。网上一些制作模板引擎的文章大部分是用正则表达式做一些hack工作,看完能收获的东西很少。本文将使用编译原理那套理论,实现模板解析和渲染,把市面上大部分模板引擎囊括其中。

整体设计

对于一个模板引擎,其主要组成部分有:

  • 模板解析器 :将模板解析成AST(抽象语法树)
  • AST优化器 :对AST进行优化
  • 渲染器 :将AST渲染为html

一个模板引擎的整体流程如下图所示:

模板引擎整体流程

模板解析

模板解析器将模板解析成AST,AST可以表示模板的结构,方便后续的优化和渲染。

词法分析

词法分析器将模板字符串切分为一个个的token,token可以是变量、表达式、标签等。例如,下面的模板:

<h1>{{title}}</h1>
<p>{{content}}</p>

词法分析器会将它切分为以下token:

[
  {
    type: 'tag',
    value: '<h1>'
  },
  {
    type: 'variable',
    value: 'title'
  },
  {
    type: 'tag',
    value: '</h1>'
  },
  {
    type: 'tag',
    value: '<p>'
  },
  {
    type: 'variable',
    value: 'content'
  },
  {
    type: 'tag',
    value: '</p>'
  }
]

语法分析

语法分析器将token序列解析成AST,AST可以表示模板的结构。例如,上面的token序列可以解析成以下AST:

{
  type: 'root',
  children: [
    {
      type: 'tag',
      value: '<h1>',
      children: [
        {
          type: 'variable',
          value: 'title'
        }
      ]
    },
    {
      type: 'tag',
      value: '<p>',
      children: [
        {
          type: 'variable',
          value: 'content'
        }
      ]
    }
  ]
}

AST优化

AST优化器对AST进行优化,以提高渲染速度。例如,AST优化器可以将相邻的文本节点合并成一个文本节点,还可以将一些不必要的节点删除。

渲染

渲染器将AST渲染为html,渲染器可以是一个函数,也可以是一个类。例如,下面的渲染器可以将上面的AST渲染为html:

function render(ast) {
  let html = '';
  for (let i = 0; i < ast.children.length; i++) {
    const child = ast.children[i];
    if (child.type === 'tag') {
      html += child.value;
      if (child.children) {
        html += render(child);
      }
    } else if (child.type === 'variable') {
      html += data[child.value];
    }
  }
  return html;
}

总结

本文介绍了如何从零编写一个模板引擎,包括模板解析、AST优化和渲染三个主要部分。希望本文能帮助你对模板引擎有更深入的了解,并能让你在实际项目中使用模板引擎。