如何让DoT.js支持Angular式模板插值,实现跨框架模板标准化?
让DoT.js支持{{modelFieldName}}格式模板语法的实现方案
我之前处理过类似的需求,要让非技术的设计师用统一的模板语法,不用记DoT.js那套带= it.的前缀,其实完全可以通过自定义DoT.js的编译规则来实现,不用提前做字符串替换,具体步骤如下:
核心思路:修改DoT的模板配置与编译逻辑
DoT.js本身提供了灵活的模板设置接口,我们可以通过调整它的语法匹配规则,同时自动给设计师写的变量名加上it.前缀,让模板在编译时自动适配DoT的上下文规则。
1. 自定义模板语法匹配规则
首先修改DoT的templateSettings,把插值语法的正则改成匹配{{modelFieldName}}这种格式,同时保留DoT原有的其他语法(比如逻辑块、条件判断这些,开发人员可能还会用到):
// 覆盖DoT默认的模板设置 doT.templateSettings = { interpolate: /{{([\s\S]+?)}}/g, // 匹配设计师写的{{变量名}}格式 encode: true, // 保持默认的HTML转义(如果不需要转义可以设为false) evaluate: /{{!([\s\S]+?)}}/g, // 保留原有的逻辑执行语法(比如{{! if(...) { }}) use: /{{#([\s\S]+?)}}/g, define: /{{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#}}/g, conditional: /{{\?(\?)?\s*([\s\S]*?)\s*}}/g, iterate: /{{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g };
2. 覆盖编译函数,自动添加it.前缀
接下来我们要修改DoT的编译逻辑,让它在处理插值的时候,自动给设计师写的变量名加上it.前缀,这样就和DoT原本的{{= it.变量名}}逻辑对齐了:
// 先保存DoT原来的编译函数 const originalCompile = doT.compile; // 自定义编译函数,处理变量前缀 doT.compile = function(template, options) { // 合并默认设置和传入的选项 const settings = {...doT.templateSettings, ...options}; // 处理所有插值语法,自动添加it.前缀 let processedTemplate = template.replace(settings.interpolate, function(match, code) { // 可选:如果变量已经写了it.开头,就不再重复添加 const trimmedCode = code.trim(); if (!trimmedCode.startsWith('it.')) { code = `it.${trimmedCode}`; } // 按照DoT默认的插值逻辑生成编译后的代码(包含空值处理和HTML转义) return `'+((${code})==null?'':${settings.encode ? doT.encodeHTML : ''}(${code}))+'`; }); // 交给原编译函数完成剩下的编译工作 return originalCompile(processedTemplate, options); };
实际使用示例
比如设计师给的SVG模板片段是这样的:
<svg width="200" height="100"> <text x="10" y="30">{{userName}}</text> <circle cx="100" cy="60" r="{{avatarRadius}}" fill="{{avatarColor}}"/> </svg>
开发人员编译并渲染的时候,只需要像平时一样传入数据:
const template = document.getElementById('svg-template').innerHTML; const render = doT.compile(template); const svgContent = render({ userName: 'Zach Scott', avatarRadius: 25, avatarColor: '#42b983' }); // 把svgContent插入到页面中即可
这样就能正确渲染出带有动态数据的SVG了,设计师完全不用关心it.前缀的问题。
额外说明
- 如果不需要HTML转义(比如变量里包含SVG标签),可以把
templateSettings.encode设为false,这样编译时就不会自动转义内容。 - 这个方案兼容DoT原有的所有其他语法(比如循环、条件判断),开发人员依然可以用
{{! if(it.isAdmin) { }}这类逻辑代码,不会冲突。
内容的提问来源于stack exchange,提问作者Zachary Scott
相关产品推荐
相关产品推荐

