首頁 > 軟體

JS模板編譯的實現詳情

2022-07-19 22:01:37

前言

編譯是一種格式變成另一種格式的過程。編譯會導致好的結果,比如書寫簡單的程式碼,編譯出來複雜的程式碼;或者提高程式碼的使用效能

這裡只聊聊模板編譯。

模板編譯的簡單實現

寫一個最簡單的模板

<p>Hello, {{name}}!</p>

這個模板用資料{name: "world"}渲染後的結果是:

<p>Hello, world!</p>

解決方法:最簡單的方案,正則替換就行了

const compile = function(template, data) {
  return template.replace(/{{(.+?)}}/g, (match, key) => data[key])
}

const template = "<p>Hello, I'm {{name}}! {{age}} years old!</p>"
const data = {
  name: "hayes",
  age: 18
}
const result = compile(template, data)
console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>

缺點很明顯,除了正則替換欄位,其他啥都幹不了,

來看看簡單的巢狀需求:

模板:

<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>

渲染資料;

const data = {
  user: {
    name: "hayes",
    age: 18
  }
}

現在再使用上面的方法,就失效了。還用正則的話,會很難做。因為需要做語法/詞法分析,來看看大括號內寫的是什麼了。

模板編譯

其實對於上述的模板,也可以使用如下方式來寫:

const compile = function(data) {
  return `<p>Hello, I'm ${data.name}! ${data.age} years old!</p>`
}

好處:只需一次編譯,之後再使用就只需要直接填充資料即可。而且也方便支援data.user.name這種形式。

工具:使用new Function生成函數

生成一個函數,傳入x和 y,執行return x + y來獲得求和的功能

const fn = new Function("x", "y", "return x + y");

列印fn可以看到輸出的內容如下:

ƒ anonymous(x,y) {
return x + y
}

1、構建模板生成函數

傳入模板字串,通過new Function方式返回一個新函數。新函數接收一個obj物件

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

2、正則替換

{{xxx}}找出來,替換為obj.xxx

const compile2 = function(template) {
  // 模板字串
  let result = template.replace(/{{(.+?)}}/g, (match, key) => {
    return `obj.${key}`
  });
  result = `return "${result}"`;
  return new Function("obj", result);
}
const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render2 = compile2(template2)
console.log(render2);

此時,函數列印如下:

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

我們需要把字串中的obj.user.nameobj.user.age變成動態的。

修改一下正則

const compile2 = function(template) {
  // 模板字串
  let result = template.replace(/{{(.+?)}}/g, (match, key) => {
    return `" + obj.${key} + "`  // 前後添上加號
  });
  result = `return "${result}"`;
  return new Function("obj", result);
}
const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render2 = compile2(template2)
console.log(render2);

再來看看函數的列印:

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

最終程式碼:

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>"
const render = compile(template)

const data = {
  user: {
    name: "hayes",
    age: 18
  }
}
const result = render(data)
console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>

渲染結果:

"<p>Hello, I'm hayes! 18 years old!</p>"

到此這篇關於JS模板編譯的實現詳情的文章就介紹到這了,更多相關JS模板編譯 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com