实例:模板编译

下面,我们来看一个通过模板字符串,生成正式模板的实例。

  1. let template = `
  2. <ul>
  3. <% for(let i=0; i < data.supplies.length; i++) { %>
  4. <li><%= data.supplies[i] %></li>
  5. <% } %>
  6. </ul>
  7. `;

上面代码在模板字符串之中,放置了一个常规模板。该模板使用<%...%>放置 JavaScript 代码,使用<%= ... %>输出 JavaScript 表达式。

怎么编译这个模板字符串呢?

一种思路是将其转换为 JavaScript 表达式字符串。

  1. echo('<ul>');
  2. for(let i=0; i < data.supplies.length; i++) {
  3. echo('<li>');
  4. echo(data.supplies[i]);
  5. echo('</li>');
  6. };
  7. echo('</ul>');

这个转换使用正则表达式就行了。

  1. let evalExpr = /<%=(.+?)%>/g;
  2. let expr = /<%([\s\S]+?)%>/g;
  3. template = template
  4. .replace(evalExpr, '`); \n echo( $1 ); \n echo(`')
  5. .replace(expr, '`); \n $1 \n echo(`');
  6. template = 'echo(`' + template + '`);';

然后,将template封装在一个函数里面返回,就可以了。

  1. let script =
  2. `(function parse(data){
  3. let output = "";
  4. function echo(html){
  5. output += html;
  6. }
  7. ${ template }
  8. return output;
  9. })`;
  10. return script;

将上面的内容拼装成一个模板编译函数compile

  1. function compile(template){
  2. const evalExpr = /<%=(.+?)%>/g;
  3. const expr = /<%([\s\S]+?)%>/g;
  4. template = template
  5. .replace(evalExpr, '`); \n echo( $1 ); \n echo(`')
  6. .replace(expr, '`); \n $1 \n echo(`');
  7. template = 'echo(`' + template + '`);';
  8. let script =
  9. `(function parse(data){
  10. let output = "";
  11. function echo(html){
  12. output += html;
  13. }
  14. ${ template }
  15. return output;
  16. })`;
  17. return script;
  18. }

compile函数的用法如下。

  1. let parse = eval(compile(template));
  2. div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
  3. // <ul>
  4. // <li>broom</li>
  5. // <li>mop</li>
  6. // <li>cleaner</li>
  7. // </ul>