模板编译

编译就是一种格局转换成另一种格局的过程,这里次要讨论一下模板编译。模板字符串比照一般的字符串有很多的不同,模板字符串能够嵌套,并且模板字符串能够在外部应用${xxx}进行表达式运算以及函数调用,这些其实都是模板编译的后果。

一般的字符串编译也就是字符拼接,如果在字符串内应用参数或者表达式,那么就须要用+号连贯,例如:

let market = document.getElementById('market')let num = 5   // 数量let money = 4  // 金额market.innerHTML = "总共卖出" + num + "杯柠檬水,总金额:" + num * money + "元"


如果用模板字符串来表白的会更加简洁,而且不须要字符串拼接,并且在外部能够间接应用表达式,例如:

market.innerHTML = `总共卖出${num}杯柠檬水,总金额:${num * money}元`

一般字符串跟模板字符串得进去的后果是一样的,能够这么说,其实就是模板字符串通过了编译解决,使字符串操作更简洁,本来须要繁琐的字符串拼接,在这里间接用模板字符串就能够解决,模板字符串是怎么样编译的呢,这里就来拆解一下模板字符串的编译过程。

1、构建模板生成函数

这里就是模板字符串编译的框架,构建一个compile 函数,通过new Function 形式返回一个新函数,新函数接管一个obj对象,通过return返回最终后果。

const compile = function (template) {            // 模板字符串            let result = ''            return new Function('obj', result)        }

2、正则替换

正则不仅能够做数据校验,还能够对传入的内容进行判断,对符合条件的内容做操作,在这里,正则起了一个替换的作用。

// 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 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"// 调用compile传入template const render = compile(template)console.log(render)

输入的后果:

 anonymous(obj) {     return "<p>Hello, I'm obj.user.name! obj.user.age years old!</p>"    }

这里例子就是将传入的字符串通过正则匹配,并且将它替换成表达式的模式obj.user.nameobj.user.age,尽管有了表达式,但它归根结底还是一个字符串,无奈编译,咱们须要把obj.user.nameobj.user.age变成动静的,并且可能编译。

3、批改正则

只须要批改一下正则即可,让字符串变成最下面提到过的,字符串拼接的模式即可。

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 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"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} + "`            // 此处就变成了 "<p>Hello, I'm " + obj.user.name + "! " + obj.user.age + " years old!</p>"            });            result = `return "${result}"`;            return new Function('obj', result);        }        const template = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"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哟