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