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

這是 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章