实现一个简易但实用的模版引擎:JST

309 阅读2分钟

前言

在业务实践过程中会遇到一些初始的代码都是相似性结构的但又不得不写的代码,之所以不能通过通用代码块引入是因为在开发过程中这部分代码总会出现各种针对性的更改,一旦抽离会丢失灵活性。

简易的类似性结构可以是这样的:

export const TEST1 = "test1" // 测试1
export const TEST2 = "test2" // 测试2

复杂点的类似性结构,可以是一个增删改查的列表页面。在实际开发中我们不得不每个新的页面都要重复实现这种相似结构的代码。那么做出点改变吧。

JST

  • 代码地址:jst

实践

  • 换个思路,我们其实可以通过模版来直接生成上面的代码
  • 模版(jst)
@map[\n]<@list@><export const <@field@> = <@value@> // <@remark@>@>
  • 数据(json)
{
    "list": [
        {
            "field": "@{TEST1}",
            "value": "test1",
            "remark": "@{测试1}"
        },
        {
            "field": "@{TEST2}",
            "value": "test2",
            "remark": "@{测试2}"
        }
    ]
}
  • 生成结果(js)
export const TEST1 = "test1" // 测试1
export const TEST2 = "test2" // 测试2

意义

  • 当数据量少的时候我们可以忍受粘贴复制,但当字段数量超过一定数量级的时候呢。
  • 可配置化生成,让我们的聚焦点只需要聚焦在代码的差异处,其他的交给引擎去生成。

定义模版规则

  • variate
    • 变量
    • <@variate = defaltValue@>
    • variate变量名
    • defaltValue为变量的默认值
  • map
    • @map[link]<@variate@>< code @>
    • 判断是否遍历生成代码块
    • link,连接符,默认为,
    • variate,数组
    • code,代码块,代码块中的变量取自数组中的单元
  • if
    • @if<@variate@>< code @>
    • 判断是否生成代码块
    • variate为判断源

实现思路

  • 先解析
    • 转化成结构化数据。
    • jst模版可以分为这几种元素:文本、变量、map语句、if语句等,都定义为类。
    • 我们用一个指针指向当前操作的对象,当此对象解析好后,指针再指向它的父级。
    • 以下为上面实践中的jst模版结构化后的数据:
    {
      "type": "list",
      "value": [
          {
              "type": "map",
              "variate": {
                  "type": "variate",
                  "field": "list",
                  "defaultValue": ""
              },
              "connector": {
                  "type": "connector",
                  "value": "\\n"
              },
              "value": {
                  "type": "list",
                  "value": [
                      {
                          "type": "text",
                          "value": "export const "
                      },
                      {
                          "type": "variate",
                          "field": "field",
                          "defaultValue": ""
                      },
                      {
                          "type": "text",
                          "value": " = "
                      },
                      {
                          "type": "variate",
                          "field": "value",
                          "defaultValue": ""
                      },
                      {
                          "type": "text",
                          "value": " // "
                      },
                      {
                          "type": "variate",
                          "field": "remark",
                          "defaultValue": ""
                      }
                  ]
              }
          }
      ]}
    
  • 后运行
    • 运行过程是从数据中取出数值,替换变量,运行代码块,然后拼接成文本的过程,这里就不多作赘述了。

最后闲聊点

  • 这套简易模版已经在老项目中得到实践,主要用于新开发的列表、表单页面,效率提升还是很明显的。
  • 通过这次自己实现这个模版引擎,更加深入的理解了脱离语言的代码解析思路,条条大路通罗马,共勉。