js 实现tmpl
JavaScript 实现模板引擎 (tmpl)
在 JavaScript 中实现一个简单的模板引擎(tmpl)可以通过多种方式完成,以下是几种常见的实现方法:
字符串替换法
使用字符串替换的方式是最基础的方法,通过正则表达式匹配占位符并替换为实际数据。
function tmpl(template, data) {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data.hasOwnProperty(key) ? data[key] : '';
});
}
// 使用示例
const template = 'Hello, {{name}}! Welcome to {{place}}.';
const data = { name: 'Alice', place: 'Wonderland' };
console.log(tmpl(template, data)); // 输出: Hello, Alice! Welcome to Wonderland.
动态函数构造法
通过 new Function 动态生成函数,利用 JavaScript 的执行能力实现模板渲染。
function tmpl(template, data) {
const keys = Object.keys(data);
const values = keys.map(key => data[key]);
const func = new Function(...keys, `return \`${template}\`;`);
return func(...values);
}
// 使用示例
const template = 'Hello, ${name}! Welcome to ${place}.';
const data = { name: 'Bob', place: 'JavaScript' };
console.log(tmpl(template, data)); // 输出: Hello, Bob! Welcome to JavaScript.
基于 DOM 的模板引擎
利用 DOM 操作和 document.createElement 实现模板渲染,适合浏览器环境。
function tmpl(template, data) {
const div = document.createElement('div');
div.innerHTML = template;
const walk = (node) => {
if (node.nodeType === Node.TEXT_NODE) {
node.textContent = node.textContent.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data[key] || '';
});
} else if (node.nodeType === Node.ELEMENT_NODE) {
Array.from(node.childNodes).forEach(walk);
}
};
walk(div);
return div.innerHTML;
}
// 使用示例
const template = '<p>Hello, {{name}}!</p>';
const data = { name: 'Charlie' };
console.log(tmpl(template, data)); // 输出: <p>Hello, Charlie!</p>
支持条件与循环的模板引擎
扩展模板引擎以支持条件判断和循环逻辑。
function tmpl(template, data) {
const codes = ['let result = [];'];
const matcher = /<%([^%>]+)?%>/g;
let cursor = 0;
let match;
const addLine = (line) => {
codes.push(`result.push(\`${line}\`);`);
};
while ((match = matcher.exec(template))) {
addLine(template.slice(cursor, match.index));
const code = match[1].trim();
if (code.startsWith('=')) {
codes.push(`result.push(${code.slice(1)});`);
} else {
codes.push(code);
}
cursor = match.index + match[0].length;
}
addLine(template.slice(cursor));
codes.push('return result.join("");');
const func = new Function(...Object.keys(data), codes.join('\n'));
return func(...Object.values(data));
}
// 使用示例
const template = `
<ul>
<% for (let i = 0; i < users.length; i++) { %>
<li><%= users[i].name %></li>
<% } %>
</ul>
`;
const data = { users: [{ name: 'Dave' }, { name: 'Eve' }] };
console.log(tmpl(template, data));
注意事项
- 安全性:动态生成代码(如
new Function)可能存在安全风险,需确保数据来源可信。 - 性能:简单的字符串替换性能较好,但复杂逻辑可能需优化。
- 兼容性:DOM 方法仅适用于浏览器环境。
以上方法可根据实际需求选择或组合使用。







