Open Inchill opened 1 year ago
上述方案存在一个问题,那就是如果我想在插值表达式里执行一些运算逻辑,那么就会报错。如果要执行一个字符串,第一时间想到的是 eval 函数,但是这仍然存在一个问题,就是 eval 执行字符串的时候,里面的变量上下文该如何获取?这时候就可以使用 with 函数,把 data 传递进去,这样就避免了访问数据时还得加上 data. 前缀。
let template = "大家好,我的名字叫做${ name.includes('H') ? name : '' },我是一名${ job },今年${ age[1] }岁。"
let data = {
name: 'Henry',
gender: 'male',
job: 'software engineer',
age: [24, 25]
}
function render (template = '', data) {
if (data === null) return
const MUSTACHE_REG = /\$\{.*?\}/ig
const KEY_REG = /(?<=\$\{(\s*?)).*?(?=(\s*?)\})/ig
return template.replace(MUSTACHE_REG, function (match = '') {
let content = match.match(KEY_REG)[0].trim()
let result
with (data) {
result = eval(content)
}
return result
})
}
console.log(render(template, data)) // 大家好,我的名字叫做Henry,我是一名software engineer,今年25岁。
第二种方案其实仍然不够好,原因就是 eval 存在安全隐患,不推荐继续使用它。能够想到的替代方案就是 new Function,把需要执行的代码拼接成字符串:
let template = "大家好,我的名字叫做 ${ name.includes('H') ? name : '' },我是一名 ${ job },今年 ${ age[1] } 岁。"
let data = {
name: 'Henry',
gender: 'male',
job: 'software engineer',
age: [24, 25]
}
function render (template = '', data) {
if (data === null) return
const MUSTACHE_REG = /\$\{.*?\}/ig
const KEY_REG = /(?<=\$\{(\s*?)).*?(?=(\s*?)\})/ig
return template.replace(MUSTACHE_REG, function (match = '') {
let content = match.match(KEY_REG)[0].trim()
let result = new Function('obj', 'with (obj) { return ' + content + '}')(data)
return result
})
}
console.log(render(template, data)) // 大家好,我的名字叫做 Henry,我是一名 software engineer,今年 25 岁。