?️Hanjst/漢吉斯特更新加JavaScript執行時優化等

wadelau發表於2019-02-17

這是 Hanjst/漢吉斯特 釋出以來的首個主要升級更新版本。這次的主要升級更新的內容包括移除HTML Comments註釋行, 優化在 Hanjst include模板檔案時的JavaScript執行時環境。

Hanjst 在設計和工程實現時,預留了模板檔案巢狀功能,由於在過往的Web軟體研發過程中,對模板檔案的套用場景非常熟悉,所以對這一需求也感觸較多,於是在最早的 Hanjst 初始釋出中就預製了模板巢狀功能。

Hanst的模板巢狀採用了與 -Smarty 等模板語言類似的語法表達:

{include file=”$anEmbedTplFile”}

其中 “anEmbedTplFile” 經由伺服器端讀取並生成想要的表示式語言字串。然後經由 Hanjst JSON Data 傳遞給 Hanjst 模板解析引擎。

Hanjst 模板引擎在解析 include 指令時,將對應的模板表示式匯入當前的頁面的當前位置,從而實現對模板的巢狀。這個過程很流暢,邏輯也與伺服器端模板語言一致。所不同於伺服器端模板語言的是,當我們在 anEbedTplFile 裡宣告 JavaScript 變數及物件時,在父模板的 JavaScript執行時環境中可能找不到該變數或物件。設若, anEmbedTplFile 中包括如下內容:

<p>This is in an Embed Tpl File</p> <script> function
embedJSFunc(varA){ console.log((new Date())+” : call embedJSFunc with
varA:”+varA); } embedJSFunc(“I’m in embed tpl file!”); </script>
<p>EOF.</p>

當我們將該模板以巢狀的形式進行嵌入一個 index.html 中時:

<p>This is in an Index Tpl File.</p> {include file=”anEmbedTplFIle”}
<p>EOF.</p>

Hanjst 在解析 index 時,會將 anEmbedTplFile 的內容合併到 index 中,同時通過 _appendScript 私有方法將 embedJSFunc 註冊到 index 中,同時在 index 的執行時環境執行 embedJSFunc 函式。

這次的主要升級改進就是這一流程中的細節進一步的優化提升。

1)資源衝突問題,當 index 中也有 embedJSFunc 同名函式時,會報錯。
該如何處理報錯資訊?
可行方法是,避免在 index 和 embed 檔案中同時命名相同的函式或變數、物件,以免引起衝突導致出錯。
即便有開發者意外地在 index 和 embed 中同樣地宣告瞭相同的函式後者變數,Hanjst 也做了異常處理,以便整體流程能夠順利執行並完成頁面渲染。

2)如果在 embed 中有 <script src=””></script>, 需要考慮引入其腳步資源。
該怎樣引入較好?
路徑中的變數如何處理?
Hanjst 此次改進增加了對 embed 的引入資源的支援,對資源路徑中的變數進行解析,如在 anEmbedTplFile 中:

<script async src=”{$tplDir}/js/adsbygoogle.js”></script>

則 Hanjst 在將 該js引入到 index時,同時解析出 {$tplDir} 所指向的真實路徑。

然而,如果是在 index 中模板中的路徑,則需要在伺服器端進行相應的替換,因為此時Hanjst 尚未接管對頁面的渲染,尤其是不能使用帶有變數的路徑來引入 Hanjst.js 檔案。

在伺服器端對資源路徑進行替換的通常做法大致過程是:A)模板開發人員,前端設計製作人員通常會使用相對資源引用路徑在交付設計稿時,B)工程技術人員拿到帶有相對資源引用路徑時,會分割出共用標頭檔案和尾檔案,其他巢狀檔案塊,然後藉由模板引擎的{include}指令,重新分割、組裝模板,C)工程技術人員將其中的相對引用路徑替換為帶有模板絕對路徑的輸出內容文字。相應的替換邏輯可以在 -GWA2 Java版中見到。

//- replaces in GWA2Java
String[] repTags = new String[]{“images”, “css”, “js”, “pics”};
for(int ti=0; ti<repTags.length; ti++){
    outx.append(“ti:[“+ti+”] reptag:[“+repTags[ti]+”]”);
    tplcont = tplcont.replaceAll(“””+repTags[ti]+”/”, “””+viewdir +”/”+repTags[ti]+”/”);
}

3)執行時序問題,如果是執行語句,繫結了相應的DOM物件,而該物件在Hanjst當前環境中還未就緒,會報錯.
該如何處理?
onComplete? window.setTimeout?

當 Hanjst 將 embed的模板內容中的指令碼注入到 index 的執行時環境時,在解決了資源衝突問題之後,需要考慮執行時序,尤其是當待執行的程式碼需要依靠 Hanjst 後續輸出的DOM 物件時,需要延後執行。

延後執行有兩種思路,依靠 JavaScript的事件驅動機制event-driven, 將待執行的動作繫結到 Hanjst 的渲染方法 _renderTemplate 之後,也即 Hanjst._renderTemplate.onComplete。 第二種思路是,依靠 JavaScript的匿名函式Anonymous Function機制,既然是延後執行,則可以將待執行的命令封裝到一個匿名函式,然後設定一個 window.setTimeout 過一段時間(預計 Hanjst 渲染完成 DOM)之後再觸發該動作。

目前,Hanjst 採用的是後一種解決執行時序問題,也即當 embed的動作要執行時,先以一個匿名函式封裝並生成一個 window.setTimeout。

執行時序問題,不單是 embed有,有時候index內的執行函式也有問題,一個常見的場景是,如果某些JavaScript呼叫是發生在 Hanjst引用之前,則會被呼叫兩次(重複!)。解決這個問題的思路就是將 待執行的命令放在 Hanjst 引用之後,或者在命令設計時,允許重複執行而不影響預計效果。

這個設計及實現可以在 Hanjst的Demo頁面看到。

Web模板語言及其解析引擎深入下去才發現,複雜而龐大,希望這些細節的探究及描述可以幫助更多的開發人員理解其內幕,僅一個{include}指令的編譯就涉及那麼多方面,一些以玩票心態用幾十行程式碼實現一個“輪子”的想法可以考慮暫停下來了。

Hanjst 解析引擎目前已經超過600行程式碼,包括很多類似這樣的算一行的統計:

var asyncScriptArr = []; var isAsync = false; var srcPos = -1; var endTagPos = -1; //- four lines
matchStr = match[0]; exprStr = match[1]; //- two lines
if(exprStr.indexOf(‘=’) > -1){ containsEqual = true; } //- three lines

毫無疑問,隨著 Hanjst 部署的例項場景越多、相容的異常越多、引入的模組越多和功能日趨強大,其程式碼會越來越長。

—-

Hanjst/漢吉斯特 是一種基於JavaScript的模板語言及解析引擎,她執行在客戶端/伺服器端。Hanjst能夠表述邏輯控制,能夠實現與伺服器端模組語言相同的功能。

Hanjst/漢吉斯特的主要特徵/功能包括:
Hanjst當完全在客戶端解析時,節省伺服器端計算資源;

Hanjst模板語言獨立,不與伺服器端資源做任何繫結;

純粹的MVC,層間資料用JSON格式傳遞;

常見模板語言功能全支援,附帶複雜而強大的JavaScript程式設計能力;

無學習成本,直接使用JavaScript書寫模板語言;

….
Hanjst 新增部署例項參考:
-Ufqi-Ztb ,
https://ztb.ufqi.com/?mod=ztb ,
全國招投標資訊中心 .

-R/s2SS

相關文章