推荐答案
-- -------------------- ---- ------- -------- ------------------------ ----- - ------ ------------------------------------- ------- ---- -- - ----- ----- - ----------------- ------ ----- --- --------- - ----- - ------ --- - -- -- ----- -------- - ------- -- ---- --- --- --- -- --- -- ----- ------ ----- ---- - - ----- -------- ---- -- -- ----- ------ - ------------------------ ------ -------------------- -- --- ------ ------ --- --- -- ----- ---- ----- --------- - --- -------- ----- -- ---------- --- - ---- ------------ ----- ----- - - ------ -------- ----- ------- - ------------------------- ------- -------------------- -- ----- -------- ----- -- ----- --- - ---- ----------
本题详细解读
核心思路
该模板引擎的核心思路是利用字符串的 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()
来动态生成函数,从而提升模板渲染的效率和灵活性(需要注意安全风险)。