手写系列之模板引擎 - 图1


实现ejs类似的功能,模板引擎。

转换效果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>模板引擎</title>
  8. </head>
  9. <body>
  10. <ul id="name_list"></ul>
  11. <script type="text/html" id="user_tmpl">
  12. <%for ( var i = 0; i < users.length; i++ ) { %>
  13. <li>
  14. <a href="<%=users[i].url%>"> <%=users[i].name%> </a>
  15. </li>
  16. <% } %>
  17. </script>
  18. <script src="index.js"></script>
  19. </body>
  20. </html>
  • 针对上述的代码实现模板引擎,让其转换为真正的html。需要转换的部分如下:
    1. <script type="text/html" id="user_tmpl">
    2. <%for ( var i = 0; i < users.length; i++ ) { %>
    3. <li>
    4. <a href="<%=users[i].url%>"> <%=users[i].name%> </a>
    5. </li>
    6. <% } %>
    7. </script>
    想要实现的效果如下:
    1. let str = ``
    2. with (data) {
    3. str += `
    4. `
    5. for (var i = 0; i < users.length; i++) {
    6. str += `
    7. <li>
    8. <a href="${users[i].url}"> ${users[i].name} </a>
    9. </li>
    10. `
    11. }
    12. str += `
    13. `
    14. }
    15. return str

    实现方案

    1. /**
    2. * @author lihh
    3. * @description 实现模板引擎 其实就是把无用的变量内容替换为字符串
    4. * @param {*} str 传递的字符串
    5. * @param {*} data 渲染的数据
    6. * @returns
    7. */
    8. function tmpl(str, data) {
    9. // 1. 将<%=XXX%> 替换为${XXX}
    10. str = str.replace(/<%=(.*?)%>/gi, '${$1}')
    11. // 2. 用变量str进行拼接,用with限定作用域
    12. let string = 'let str = ``; \r\n with(data){'
    13. string += 'str += `'
    14. // 3. 以<%XXX%> 为界限进行分割,进行字符串的拼接
    15. string += str.replace(/<%(.+?)%>/gi, function () {
    16. return '`\r\n' + arguments[1] + '\r\n str += `'
    17. })
    18. string += '` \r\n } \r\n return str'
    19. // 4. new Function 来运行字符串
    20. const fn = new Function('data', string)
    21. return fn(data)
    22. }