You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中实现支持嵌套数据与函数的简单模板引擎?

实现极简模板引擎:支持嵌套数据与自定义函数调用

核心问题拆解

你当前的实现只能处理单层属性访问,无法解析嵌套路径(如profile.name)和函数调用逻辑。要满足需求,需要解决两个核心问题:

  1. 解析多层嵌套的属性路径
  2. 识别并执行带参数的自定义函数

具体实现方案

完整代码实现

export class TemplateEngine {
  public static render(template, data, functions = {}) {
    // 匹配{{}}内的所有表达式,兼容换行和空格
    return template.replace(/{{\s*([\s\S]+?)\s*}}/g, (_, expr) => {
      // 判断是否为函数调用(包含())
      const funcCallMatch = expr.match(/^(\w+)\((.*)\)$/);
      if (funcCallMatch) {
        const [_, funcName, argsStr] = funcCallMatch;
        const targetFunc = functions[funcName];
        if (!targetFunc) return '';

        // 解析参数:区分字符串字面量和属性路径
        const args = argsStr.split(/\s*,\s*/).map(arg => {
          // 处理单/双引号包裹的字符串
          const strLiteralMatch = arg.match(/^(['"])(.*)\1$/);
          if (strLiteralMatch) {
            return strLiteralMatch[2];
          }
          // 处理属性路径参数
          return TemplateEngine.resolvePath(data, arg.trim());
        });

        return targetFunc(...args);
      }

      // 处理嵌套属性访问
      return TemplateEngine.resolvePath(data, expr.trim());
    });
  }

  // 工具方法:解析嵌套属性路径
  private static resolvePath(obj, path) {
    return path.split('.').reduce((current, key) => {
      return current && current[key] !== undefined ? current[key] : '';
    }, obj);
  }
}

关键逻辑说明

  1. 正则匹配优化:使用/{{\s*([\s\S]+?)\s*}}/g匹配表达式,兼容表达式内的空格和换行,同时精准捕获内容。
  2. 嵌套属性解析:通过resolvePath方法,将profile.name这类路径拆分为数组,逐层从数据对象中取值,处理多层嵌套。
  3. 函数调用处理:
    • 用正则识别函数调用格式(如formatDate(...)),提取函数名和参数字符串
    • 拆分参数时,区分单/双引号包裹的字符串字面量和属性路径参数
    • 从传入的functions对象中获取目标函数,执行并返回结果

测试验证

使用你提供的示例测试:

// 假设已引入moment库
TemplateEngine.render(
  'Hello {{profile.name}}, the following date {{formatDate(event.date, \'dd.mm.yyyy\')}} is free.',
  {
    profile: { name: 'Tom' },
    event: { date: 1682349765 }
  },
  {
    formatDate: (input, format) => moment.unix(input).format(format)
  }
);
// 输出结果:Hello Tom, the following date 24.04.2023 is free.

扩展支持文本处理函数

你可以直接在functions参数中添加所需的文本处理函数,比如:

// 示例扩展函数
const textFunctions = {
  uppercase: (str) => str.toUpperCase(),
  substring: (str, start, end) => str.substring(start, end),
  trim: (str) => str.trim()
};

// 使用示例
TemplateEngine.render(
  'Name: {{uppercase(profile.name)}}, Trimmed: {{trim(profile.nickname)}}',
  { profile: { name: 'tom', nickname: '  TomCat  ' } },
  textFunctions
);
// 输出:Name: TOM, Trimmed: TomCat

内容的提问来源于stack exchange,提问作者perotom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:05:25