1. 首先建立render函数挂载在String的原型上
// data参数是一个对象,会将其中的属性值替换到字符串中
String.prototype.render = function(data = {}) {}
2. 使用正则表达式查找占位符 {{ name }}
String.prototype.render = function(data) {
/*
regExp: /{{[.\s\S]*?}}/g
用于匹配{{}}包括的所有内容,包括换行,因为要支持在其中放置js代码
此时回调参数match代表的是匹配到的字符串,返回后的数据会将匹配到的字符串替换
*/
return this.replace(/{{[.\s\S]*?}}/g, match => {});
}
3. 编写render内部代码
// 将{{}}一对大括号过滤掉并赋值给match,并且去除首尾空格,如果去除以后内容是空,那么替换成空字符串
if((match = match.substring(2, match.length - 2).trim()) == "") {
return "";
} else if (match.startsWith("#")) {
// 如果开头是#,那么被认为是js代码,使用eval执行,其中使用变量需要 data.变量名
return eval(match.substr(1, match.length - 1));
} else {
// 否则被认作为普通变量,使用data中的属性替换
return data[match] ? data[match] : "";
}
/*
这里将js代码和普通变量使用判断分开,避免普通变量也使用eval影响效率
*/
4. 成品
String.prototype.render = function(data) {
return this.replace(/{{[.\s\S]*?}}/g, match => {
if ((match = match.substring(2, match.length - 2).trim()) == "") {
return "";
} else if (match.startsWith("#")) {
return eval(match.substr(1, match.length - 1));
} else {
return data[match] ? data[match] : "";
}
})
}
const data = {
name: "小明",
age: 16,
school: "第三中学",
classroom: "教室2"
}
console.log(
"{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data)
);
// 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年
console.log(
`{{name}}说了句{{#
if (data.age >= 18) {
"我已经成年了!"
} else {
"我还没有成年!"
}
}}`.render(data)
);
// 小明说了句我还没有成年!