推荐答案
// www.javascriptcn.com code example
function templateEngine(template, data) {
return template.replace(/\{\{([^{}]+)\}\}/g, (match, key) => {
const value = data[key.trim()];
return value !== undefined ? value : match;
});
}
// 示例
const template = "Hello, {{ name }}! You are {{ age }} years old.";
const data = { name: "Alice", age: 30 };
const result = templateEngine(template, data);
console.log(result); // 输出: Hello, Alice! You are 30 years old.
const template2 = "My favorite color is {{color}}, and I like {{fruit}}.";
const data2 = { color: "blue"};
const result2 = templateEngine(template2, data2);
console.log(result2) // 输出:My favorite color is blue, and I like {{fruit}}.本题详细解读
核心思路
该模板引擎的核心思路是利用字符串的 replace() 方法结合正则表达式来实现简单的模板替换。正则表达式 \{\{([^{}]+)\}\} 匹配形如 {{ key }} 的占位符,并捕获 key。 replace() 方法的第二个参数是一个回调函数,该函数接收匹配到的字符串和捕获的 key。在回调函数中,我们从传入的 data 对象中获取 key 对应的 value。如果 value 存在,则将其替换占位符,否则保持占位符不变。
代码详解
function templateEngine(template, data):- 定义一个名为
templateEngine的函数,接受两个参数:template(模板字符串) 和data(数据对象)。
- 定义一个名为
template.replace(/\{\{([^{}]+)\}\}/g, (match, key) => { ... });:- 使用
replace()方法在模板字符串中查找所有符合正则表达式\{\{([^{}]+)\}\}的子字符串。 /\{\{([^{}]+)\}\}/g: 这是一个正则表达式:\{\{和\}\}: 匹配字面量{{和}}。([^{}]+): 这是一个捕获组,[]表示匹配括号内的任何一个字符,^表示非,[^\{\}]表示匹配除{和}以外的任何字符,+表示匹配前面的字符一次或多次. 整体含义是匹配{{和}}之间的任何非{或}的字符,并将它们捕获到一个组中。g: 全局匹配标志,表示匹配所有符合条件的子字符串,而非仅匹配第一个。
(match, key) => { ... }: 这是一个回调函数,针对每个匹配到的子字符串执行。match: 表示匹配到的完整字符串 (例如{{ name }}).key: 表示正则表达式捕获组的内容 (例如name),也就是要替换的键名。
- 使用
const value = data[key.trim()];:- 从
data对象中,使用key作为属性名获取对应的值value。使用key.trim()去除key左右两侧的空格。
- 从
return value !== undefined ? value : match;:- 这是一个三元运算符。
- 如果
value存在(即不是undefined),则返回value,用于替换占位符。 - 如果
value不存在(即是undefined),则返回原始的match字符串,保持占位符不变。
优点
- 简单易懂: 代码逻辑清晰,容易理解和维护。
- 轻量级: 不需要额外的库,代码量少。
- 易于使用: 使用方式简单直接。
缺点
- 功能有限: 仅支持简单的占位符替换,不支持复杂的逻辑控制(如循环、条件判断等)。
- 安全性: 没有进行任何的输入验证,如果
data中包含了恶意脚本,可能会造成 XSS 漏洞。
扩展思路
- 可以考虑引入更复杂的语法,例如支持
{{if condition}} ... {{else}} ... {{/if}}这样的条件渲染。 - 可以使用
with语句或者new Function()来动态生成函数,从而提升模板渲染的效率和灵活性(需要注意安全风险)。