成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

讀mmTemplate by RubyLouvre

Sleepy / 3266人閱讀

試著分析下正美大大的模板
https://github.com/RubyLouvre/mmTemplate/blob/master/mmTemplate.js

首先是一trim函數(shù),把字符串兩端的空白字符去掉

然后是根據(jù)id獲取模板字符串,用ejs.compile(source)編譯成模版函數(shù)

最后用data來調(diào)用模版函數(shù)

這3步驟中有一些細節(jié)處理

用ejs.cache[id]緩存模版函數(shù),防止重復(fù)編譯

$(id, doc)[0] || doc.querySelectorAll(id)[0] || doc.getElementById(id.slice(1)) 降級使用dom選擇器

針對 script textarea標(biāo)簽內(nèi)的文本進行unescape處理

opts對象用來配置
opts.doc 模板文檔對象
opts.tid 模板緩存id:string
opts.open tops.close 開始關(guān)閉標(biāo)簽 默認 瀏覽器端為:"<&&>" nodejs端為:""
opts.[helpername] 在模板內(nèi)部使用的自定義輔助函數(shù)

于是主要就是ejs.compile函數(shù)的編譯過程
首先對于其提供的模板例子

        

編譯函數(shù)根據(jù)分割符號<&&> 將其分割,現(xiàn)在用|||為大家標(biāo)記出來如下:

            |||= title() |||
            
                |||- for(var i=0,tl = @trs.length,tr;i
                        
                    ||| } |||
            
|||= tr.name;; ||| |||= tr.age; ||| |||= tr.sex || "男" |||
|||# 怎么可能不支持圖片 |||

這些由|||分割的片段被分為 普通字符串js邏輯 兩大類
分割方法是設(shè)置一個標(biāo)志位 flag=true
flag === true 的時候為普通字符串【默認值】
flag === false 的時候為js邏輯
由于<&&>是開始、閉合一一相對的,于是可以根據(jù)當(dāng)前flag的值flag ? open : close去查找到下一個分隔符的開關(guān)類型和位置
普通js邏輯字符串分別被存放于 codesjs數(shù)組中

同時,按照字符的順序同步進行的是把所有的字符串編譯成為一個匿名函數(shù)
先來一個時間字符串

var time = new Date * 1; // 1399372159719

匿名函數(shù)anonymous最終調(diào)用形式為anonymous(codes, js, filters, helpers)
于是編譯函數(shù)分別給 codes,js 映射了一個形式參數(shù)名 txt1399372159719, js1399372159719
現(xiàn)在匿名函數(shù)顯示如下:

function anonymous(txt1399372159719, js1399372159719, filters, title ) {
  return function(data) {
    "use strict";
    try {
      var r = "",
      line1399372159719 = 0;

當(dāng)遇到普通字符串的時候,會轉(zhuǎn)換成語句

r += txt1399372159719[index];

到遇到輔助函數(shù)<&= title() &>時轉(zhuǎn)換為:

r += title();

遇到<&- for(var i=0,tl = @trs.length,tr;i為:

for (var i = 0, tl = data.trs.length, tr; i < tl; i++) {;

其他類推
最終函數(shù)【格式化后】為:

function anonymous(txt1399372159719, js1399372159719, filters, title /**/ ) {
  return function(data) {
    "use strict";
    try {
      var r = "",
      line1399372159719 = 0;;
      r += txt1399372159719[0];;
      line1399372159719 = 1;;
      r += title();;
      r += txt1399372159719[1];;
      line1399372159719 = 2;
      for (var i = 0, tl = data.trs.length, tr; i < tl; i++) {;
        r += txt1399372159719[2];;
        line1399372159719 = 3;
        tr = data.trs[i];;
        r += txt1399372159719[3];;
        line1399372159719 = 4;;
        r += tr.name;;;;
        r += txt1399372159719[4];;
        line1399372159719 = 5;;
        r += tr.age;;;
        r += txt1399372159719[5];;
        line1399372159719 = 6;;
        r += tr.sex || "男";;
        r += txt1399372159719[6];;
        line1399372159719 = 7;
      };
      r += txt1399372159719[7];;
      line1399372159719 = 8;;
      r += txt1399372159719[8];;
      line1399372159719 = 9;;
      r += data.href;;
      r += txt1399372159719[9];
      return r;
    } catch (e) {
      EJS.log(e);
      EJS.log(js1399372159719[line1399372159719 - 1])
    }
  }
}

注意到

生成的函數(shù)堪比手寫但有一些冗余的分號;防止語句沖突問題

trim=true的方式處理標(biāo)簽冗余空白,適用于不需要生成多余空白的情況

@trs.length等語句會被轉(zhuǎn)化為 data.trs.length,而不是簡單的獲取全局變量

|過濾器會被收集起來,然后一個一個的執(zhí)行順序嵌套執(zhí)行

#注釋語句將被完全忽略

helpers是被數(shù)組化,然后按照形式參數(shù)一次被匿名函數(shù)調(diào)用的【參考title函數(shù)】

對于line1399372159719這個變量,我猜測是用于記錄編譯結(jié)果函數(shù)的行數(shù)的,具體還不是很明白,希望知道的同學(xué)可以幫忙解釋一下

這部分的代碼都位于js邏輯字符串分支的處理中
生成函數(shù)的方式為 Function.apply,這段代碼可以欣賞一下

        var body = ["txt"+time,"js"+time, "filters"]

        var fn = Function.apply(Function, body.concat(helperNames,t) );
        // console.log(fn.toString())
        var args = [codes, js, EJS.filters];
        var compiled = fn.apply(this, args.concat(helpers));

最后編譯函數(shù)被(緩存)返回,供我們調(diào)用 fn(data)

好厲害的代碼,我還要打個飽嗝再慢慢消化下。
特別是對于

  

line1399372159719 這個變量的作用 還在疑惑中,希望有人可以幫忙解釋下?

the End.

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78088.html

相關(guān)文章

  • React16.2的fiber架構(gòu)(2)

    摘要:為了幫助理解,我們繼續(xù)加日志司徒正美,加群一起研究與只要收到更新對象,就會被調(diào)度程序調(diào)用。渲染器在將來的某個時刻調(diào)用。導(dǎo)步肯定為歡迎加繼續(xù)略也是怒長,代碼的特點是許多巨型類,巨型方法,有之遺風(fēng)。 insertUpdateIntoFiber 會根據(jù)fiber的狀態(tài)創(chuàng)建一個或兩個列隊對象,對象是長成這樣的 //by 司徒正美, 加群:370262116 一起研究React與anujs //...

    Caicloud 評論0 收藏0
  • React16.2的fiber架構(gòu)

    摘要:司徒正美,加群一起研究與用于調(diào)整渲染順序,高優(yōu)先級的組件先執(zhí)行這只是一部分更新邏輯,簡直沒完沒了,下次繼續(xù)添上流程圖,回憶一下本文學(xué)到的東西 React16真是一天一改,如果現(xiàn)在不看,以后也很難看懂了。 在React16中,雖然也是通過JSX編譯得到一個虛擬DOM對象,但對這些虛擬DOM對象的再加工則是經(jīng)過翻天覆地的變化。我們需要追根溯底,看它是怎么一步步轉(zhuǎn)換過來的。我們先不看什么組件...

    lansheng228 評論0 收藏0
  • 《機票航班列表》項目總結(jié)

    摘要:很快沒在公司參考這么大的項目升級工作了。第二個是事件,這兩個事件無法冒泡,而的事件系統(tǒng)是建立在事件代理的基石之上。最大的收獲是,終于有高度可用的版本了,也有一個可以為自己代言的大項目,我們的調(diào)試技術(shù)又大大提高了二分法總是最有效的。 很快沒在公司參考這么大的項目升級工作了。工作的內(nèi)容聽起來很簡單,將React改成我們平臺事業(yè)部的迷你React框架Qreact(https://github...

    davidac 評論0 收藏0
  • Luy 1.0 :一個React-like輪子的誕生

    摘要:司徒正美的一款了不起的化方案,支持到。行代碼內(nèi)實現(xiàn)一個胡子大哈實現(xiàn)的作品其實就是的了源碼學(xué)習(xí)個人文章源碼學(xué)習(xí)個人文章源碼學(xué)習(xí)個人文章源碼學(xué)習(xí)個人文章這幾片文章的作者都是司徒正美,全面的解析和官方的對比。 前言 在過去的一個多月中,為了能夠更深入的學(xué)習(xí),使用React,了解React內(nèi)部算法,數(shù)據(jù)結(jié)構(gòu),我自己,從零開始寫了一個玩具框架。 截止今日,終于可以發(fā)布第一個版本,因為就在昨天,我...

    codecook 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<