Open fedono opened 3 years ago
function render(tpl, data) {
// 第一步,匹配到所有的 {{}} 的数据,然后开始做替换
return tpl.replace(/\{\{[^}]+\}\}/g, $1 => {
// 把单个的 {{}} 中的 {{ }} 和空白字符串删除掉
let name = $1.replace(/[{}]/g, '').replace(/\s+/g, '');
if (data[name]) {
return data[name];
} else {
let res = [];
// 有 group.name 和 group.jobs[0] 、group["jobs"][1] 三者情况,所以划分一下,先使用.分割开来,然后就可以分别处理含有 [] 的情况了
let names = name.split('.');
names.forEach(item => {
if (item.includes('[')) {
// 这里要拿到 group["jobs"][1] 中的 group 这个,使用的是 positive lookahead 的方式
item.replace(/([^\[]+)(?=\[)/, $1 => {
if ($1) {
res.push($1);
}
});
// 匹配到 [] 的情况
item.replace(/(\[['"]?)[^\[\]]+(['"]?\])/g, $1 => {
// 将[ 和 ] 拿到,然后 replace 掉
let v = $1.replace(/\[(['"])?|/, '').replace(/(['"])?\]/, '').replace(/\s+/g, '');
res.push(v);
return $1;
});
}
else {
res.push(item.replace(/\s+/g, ''));
}
})
// 通过一个循环,从data 里面拿到 数据
let temp = JSON.parse(JSON.stringify(data));
while (res.length) {
temp = temp[res.shift()];
};
return temp;
}
});
}
那个时候还天真,还不知道 eval 和 new Function 的妙用
使用 new Function
来直接获取到这个属性的值
function render(template, data) {
return template.replace(/\{\{([^\}\}]+)\}\}/g, ($1) => {
let name = $1.replace(/[{}]/g, '').trim()
fn = new Function('data', `with(data) return ${name}`)
let content = fn(data)
return content;
})
}
使用 eval
来获取属性的值
function render(template, data) {
return template.replace(/\{\{([^\}\}]+)\}\}/g, ($1) => {
const name = $1.replace(/[{}]/g, '').trim()
const content = eval(`data.${name}`)
return content;
})
}
实现一个 render 函数,第一个参数是模板,第二个参数是数据,将数据映射到模板中