HTML字符串模板


HTML字符串模板是在写页面模板时会用到的一个渲染引擎,本质是字符串替换和代码执行。格式是下面这样子的:

输出值:

<html><body>
<%= name %>
</body></html>

执行代码

<html><body><% for(var i = 0; i < 2; i++) {%><div><%= i %></div><% } %></body></html>

就是使用<% 和<%=分别表示执行代码和输出变量的值,用%>表示自定义的结束。语法很简单,不考虑复杂情况下,可以自己动手实现一个。

1. 替换思路

      把整个HTML模板读取成字符串后,将HTML部分当作是字符串,将<% %>和<%= %>中间部分取出进行执行。由于<% %>只是执行代码,不直接输出HTML模板,不用处理返回结果。而<%= %>需要把表示式的返回值保存起来,加到输出结果中。

      要根据输入对象,直接读取值,可以用with方法。虽然该方法已经不被推荐,但在这种情况下应用还是很方便。将模板解析后,使用new Function生成函数,代入输入对象,即可实现替换。

2. 实现

module.exports = function regTemplate (str, obj) {

  let pre = 'with(obj){var _str = "";_str +=\''

  let evalStr = str

    .replace(/[\r\n\t]/g, ' ')
    .replace(/<%=([\s\S]*?)%>/g, "';_str +=$1;_str +='")
    .replace(/<%/g, "';")
    .replace(/%>/g, "_str+='")

  evalStr = pre + evalStr + "';return _str;}"
  var func = new Function ('obj', evalStr)
  return func(obj)
}

 

       代码如上。核心是在with时建立一个空白字符串,用str+=‘ 将第一个html片断加入到结果字符串中,然后遇到<%= %>时, html字符串结束,添加内部表达式的值,再开始加一下个字符串。遇到<%时,html字符串结束,里面的内容不用处理,直接遇到%>表示应该开始下一字符串,再进行相加HTML字符串。最后添加结尾单引号。

       使用new Function生成新函数,代入输入的对象,返回执行结果。

  当然,光这样还是不够的,由于HTML中代码中虽然只推荐使用双引号,但还是有可能出现单引号,这时模板就会失效。改进一下:

module.exports = function regTemplate (str, obj) {

  let pre = 'with(obj){var _str = "";_str +=\''

  // replace last single quote
  let arr = str.split('%>')
  arr[arr.length - 1] = arr[arr.length - 1].replace(/'/g, '\\\'')
  str = arr.join('%>')

  let evalStr = str
    // replace first single quote
    .replace(/([\s\S]*?)<%/m, function (str, $1) { return $1.replace(/'/g, '\\\'') + '<%' })
    // replace middle single quote
    .replace(/%>([\s\S]*?)<%/g, function (str, $1) { return '%>' + $1.replace(/'/g, '\\\'') + '<%' })
    .replace(/[\r\n\t]/g, ' ')
    .replace(/<%=([\s\S]*?)%>/g, "';_str +=$1;_str +='")
    .replace(/<%/g, "';")
    .replace(/%>/g, "_str+='")

  evalStr = pre + evalStr + "';return _str;}"
  var func = new Function ('obj', evalStr)
  return func(obj)
}

使用正则替换掉中间和第一段中的单引号。但最后一段的正则我不会写,尝试了好久也没成功,没办法只能用字符串处理了,导致程序代码一下子就多了起来,看起来很不舒服。先这样了。

3. 总结

  写起来很费劲,想了好久也没想出方案,最后还是按https://www.cnblogs.com/dolphinX/p/3489269.html上面实现的。主要问题还是思路没有理清,尤其是关于<% %>这种不处理成字符串的,浪费了很多时间。再者正则使用是一知半解,一遇到复杂的就很难写。

  附上练习源码地址:https://github.com/wenlonghuo/code-test/tree/master/002_htmlTemplate

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM