js实现模板引擎
实现简单模板引擎
使用字符串替换方法实现基础模板引擎功能。定义一个模板字符串,通过占位符标记需要替换的部分,利用正则表达式匹配占位符并进行替换。
function simpleTemplate(template, data) {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data[key] || '';
});
}
const template = 'Hello, {{name}}! Today is {{day}}.';
const data = { name: 'Alice', day: 'Monday' };
console.log(simpleTemplate(template, data)); // Hello, Alice! Today is Monday.
处理复杂表达式
扩展模板引擎以支持对象属性访问和简单表达式。通过更复杂的正则表达式匹配模板中的JavaScript表达式,并使用Function构造函数动态执行。

function advancedTemplate(template, data) {
return template.replace(/\{\{(.+?)\}\}/g, (match, exp) => {
try {
return new Function('data', `with(data){return ${exp}}`)(data);
} catch {
return '';
}
});
}
const template = 'User: {{user.name}}, Age: {{user.age + 1}}';
const data = { user: { name: 'Bob', age: 25 } };
console.log(advancedTemplate(template, data)); // User: Bob, Age: 26
实现条件渲染
添加条件判断支持,使用特殊语法标记条件块。通过正则表达式分割模板字符串,解析条件逻辑并决定是否渲染特定部分。
function conditionalTemplate(template, data) {
const ifRegex = /\{\{if\s+(.+?)\}\}(.+?)\{\{\/if\}\}/gs;
return template.replace(ifRegex, (match, condition, content) => {
const test = new Function('data', `with(data){return !!(${condition})}`)(data);
return test ? content : '';
});
}
const template = '{{if user.admin}}Admin Access{{/if}}';
const data1 = { user: { admin: true } };
const data2 = { user: { admin: false } };
console.log(conditionalTemplate(template, data1)); // Admin Access
console.log(conditionalTemplate(template, data2)); // (空字符串)
实现循环渲染
支持数组遍历功能,解析循环语法并重复渲染模板片段。处理数组数据时,为每次迭代创建新的上下文。

function loopTemplate(template, data) {
const eachRegex = /\{\{each\s+(\w+)\s+as\s+(\w+)\}\}(.+?)\{\{\/each\}\}/gs;
return template.replace(eachRegex, (match, arrayName, itemName, content) => {
const array = new Function('data', `with(data){return ${arrayName}}`)(data) || [];
return array.map(item => {
return content.replace(/\{\{(\w+)\}\}/g, (m, key) => {
return item[key] || '';
});
}).join('');
});
}
const template = '{{each users as user}}<li>{{user.name}}</li>{{/each}}';
const data = { users: [{ name: 'Alice' }, { name: 'Bob' }] };
console.log(loopTemplate(template, data)); // <li>Alice</li><li>Bob</li>
缓存编译模板
优化性能,预先编译模板为可执行函数。将模板字符串转换为函数并缓存,减少重复解析的开销。
const templateCache = {};
function compileTemplate(template) {
if (templateCache[template]) return templateCache[template];
const code = `with(data){return \`${template
.replace(/\{\{if\s+(.+?)\}\}/g, '`;$1?`')
.replace(/\{\{\/if\}\}/g, '`:``')
.replace(/\{\{each\s+(\w+)\s+as\s+(\w+)\}\}/g, '`;${$1}.map($2=>`')
.replace(/\{\{\/each\}\}/g, '`).join("")+`')
.replace(/\{\{(.+?)\}\}/g, '${$1}')
}\`}`;
templateCache[template] = new Function('data', code);
return templateCache[template];
}
function cachedTemplate(template, data) {
const render = compileTemplate(template);
return render(data);
}
const template = '{{if show}}Hello{{/if}} {{each items as item}}{{item}}{{/each}}';
const data = { show: true, items: [1, 2, 3] };
console.log(cachedTemplate(template, data)); // Hello 123
安全考虑
避免使用with语句可能带来的安全问题,改用更安全的上下文处理方式。限制可访问的变量,防止原型污染。
function safeTemplate(template, data) {
const allowed = new Set(Object.keys(data));
const sandbox = Object.create(null);
Object.keys(data).forEach(key => {
Object.defineProperty(sandbox, key, {
enumerable: true,
get: () => data[key]
});
});
const code = `return \`${template
.replace(/\{\{(.+?)\}\}/g, '${$1}')
}\``;
try {
return new Function('sandbox', code).call(null, sandbox);
} catch {
return '';
}
}
const template = 'Hello {{name}}! {{toString}}';
const data = { name: 'Charlie' };
console.log(safeTemplate(template, data)); // Hello Charlie!






