编译就是一种格式转换成另一种格式的过程,这里主要讨论一下模板编译。模板字符串对比普通的字符串有很多的不同,模板字符串可以嵌套,并且模板字符串可以在内部使用${xxx}
进行表达式运算以及函数调用,这些其实都是模板编译的结果。
普通的字符串编译也就是字符拼接,如果在字符串内使用参数或者表达式,那么就需要用+
号连接,例如:
let market = document.getElementById('market') let num = 5 // 数量 let money = 4 // 金额 market.innerHTML = "总共卖出" + num + "杯柠檬水,总金额:" + num * money + "元"
如果用模板字符串来表达的会更加简洁,而且不需要字符串拼接,并且在内部可以直接使用表达式,例如:
market.innerHTML = `总共卖出${num}杯柠檬水,总金额:${num * money}元`
普通字符串跟模板字符串得出来的结果是一样的,可以这么说,其实就是模板字符串经过了编译处理,使字符串操作更简洁,原本需要繁琐的字符串拼接,在这里直接用模板字符串就可以解决,模板字符串是怎么样编译的呢,这里就来拆解一下模板字符串的编译过程。
这里就是模板字符串编译的框架,构建一个compile
函数,通过new Function
方式返回一个新函数,新函数接收一个obj
对象,通过return
返回最终结果。
const compile = function (template) { // 模板字符串 let result = '' return new Function('obj', result) }
正则不仅可以做数据校验,还可以对传入的内容进行判断,对符合条件的内容做操作,在这里,正则起了一个替换的作用。
// compile 函数 const compile = function (template) { // 模板字符串 let result = template.replace(/{ {(.+?)}}/g, (match, key) => { return `obj.${key}` }); result = `return "${result}"`; return new Function('obj', result); } // 字符串模板 const template = "Hello, I'm { {user.name}}! { {user.age}} years old!" // 调用compile传入template const render = compile(template) console.log(render)
输出的结果:
anonymous(obj) { return "Hello, I'm obj.user.name! obj.user.age years old!" }
这里例子就是将传入的字符串通过正则匹配,并且将它替换成表达式的形式obj.user.name
、obj.user.age
,虽然有了表达式,但它归根结底还是一个字符串,无法编译,我们需要把obj.user.name
、obj.user.age
变成动态的,并且能够编译。
只需要修改一下正则即可,让字符串变成最上面提到过的,字符串拼接的形式即可。
const compile = function (template) { // 模板字符串 let result = template.replace(/{ {(.+?)}}/g, (match, key) => { // 前后加上引号 return `" + obj.${key} + "` }); result = `return "${result}"`; return new Function('obj', result); }
在template.replace
这里,将符合条件的位置替换,变成字符串拼接的形式。
const data = { user: { name: 'hayes', age: 18 } } const template = "Hello, I'm { {user.name}}! { {user.age}} years old!" const render = compile(template) const result = render(data) console.log(result)
传入的值经过了处理,在template.replace
下面的return
这里实际上将字符串变成了这种形式
只需要将返回的结果渲染到页面即可,最终的结果:
const compile = function (template) { // 模板字符串 let result = template.replace(/{ {(.+?)}}/g, (match, key) => { // 前后加上引号 return `" + obj.${key} + "` // 此处就变成了 "Hello, I'm " + obj.user.name + "! " + obj.user.age + " years old!" }); result = `return "${result}"`; return new Function('obj', result); } const template = "Hello, I'm { {user.name}}! { {user.age}} years old!" const render = compile(template) const data = { user: { name: 'hayes', age: 18 } } const result = render(data) console.log(result)
案例源码:https://gitee.com/wang_fan_w/es6-science-institute
如果觉得这篇文章对你有帮助,欢迎点亮一下star哟
Copyright © 2023 leiyu.cn. All Rights Reserved. 磊宇云计算 版权所有 许可证编号:B1-20233142/B2-20230630 山东磊宇云计算有限公司 鲁ICP备2020045424号
磊宇云计算致力于以最 “绿色节能” 的方式,让每一位上云的客户成为全球绿色节能和降低碳排放的贡献者