【仿doT前端模板】二、if else

来源:http://www.cnblogs.com/t-lll/archive/2017/05/10/6838423.html
-Advertisement-
Play Games

效果預覽 首先,按照慣例,我們先看doT 實現的效果: 模板: {{? it.name }} <div>嗨, {{=it.name}}!</div> {{?? it.age 0}} <div>我猜應該還沒人給你起名字吧?</div> {{??}} 你已經 {{=it.age}} 歲了但是你還沒有名字 ...


效果預覽

首先,按照慣例,我們先看doT 實現的效果:

模板:

{{? it.name }}
    <div>嗨, {{=it.name}}!</div>
{{?? it.age === 0}}
    <div>我猜應該還沒人給你起名字吧?</div>
{{??}}
    你已經 {{=it.age}} 歲了但是你還沒有名字?
{{?}}

 

數據結果
{name:'十一川'} <div>嗨, 十一川! </div>
{age:0} <div>我猜應該還沒人給你起名字吧?</div>
{age:11} <div>你已經 11 歲了但是你還沒有名字?</div>

實現思路

我們此次要做的事情,與上次一樣,無非是一個 查找標記 => 替換成對應代碼 的過程 而區別在於,我們此次要替換的標記不再是一個,而是4個:

標記 結果
{{? it.name }} => if( it.name ){
{{?? it.age === 0}} => } else if( it.age === 0 ) {
{{??}} => } else{
{{?}} => }

實現過程

寫出正則表達式

var IF = /\{\{\?([^\?]{1}.*?)\}\}/g;
var ELSE_IF = /\{\{\?\?(.+?)\}\}/g;
var ELSE = /\{\{\?\?\}\}/g;
var END_IF = /\{\{\?\}\}/g;

 

這裡需要特別註意的是,匹配if 與其他標記的包含關係,也就是說,如果我們匹配的是:

 

那麼,else標記的{{??}}中的第二個? 會被當成條件,也就是說:

 

甚至於,我們作為結尾的{{?}}也會被當成沒有條件的if語句:

 

 

這很明顯不是我們想要達到的效果啊!

要解決這個問題,首先能想到的簡單粗暴的辦法就是。。。我們可以先把{{??}}{{?}}標記替換掉嘛,這樣不就等到替換{{? 條件}}的時候,我們就能保證全部都是條件語句了。

唔。。。這固然是個“暫時能用的辦法”,但是萬一哪天,我們心血來潮地把賦值{{= 值}}改成了這樣:{{??? 值}},那我們還得去代碼里看看值的替換是否在if替換之前?

 

有!我們不難推導出,這裡的“條件”要先符合兩個條件:

  • 第一個字元不能是?這個字元本身
  • 不能為空

這樣的話,不管我們替換的順序如何,都能保證不會影響到其他的標記,那麼,這兩個限定又如何通過正則表達式表達出來呢?

我們可以通過^符號來表示“不能是某個字元”,而我們要表示“不能是?的一個字元”的話自然就是[^\?];而{1}來表示“有且只有一個字元”。因此([^\?]{1}.*?)表示的就是“最起碼一個字元,而且第一個字元不能是?的任意長度字元串” ,自然就是我們一開始提到的if的正則表達式。

順帶一提,為什麼只限制了“第一個字元不能是?這個字元”,而不是“所有字元”呢?這是因為三元操作符?:能夠產生一個合法的bool值,比如:a?2:3,如果我們只是粗暴地規定“所有的條件中都不能包含?”那麼可能會導致原本合法的表達式沒有被當成條件。而這個表達式的?前面最起碼要有一個變數名,變數名最短也是一個非?的字元,因此在這個層面,我們僅僅限定住“第一個字元”,是有著必要性和充分性的。

而類似的,為了防止 else 的標記被當成“沒有條件的 else if 標記” 我們同樣要對這裡的條件作出“起碼有一個字元的限制” ,也就是(.+?)

引入out

現在,我們還有一個問題是,因為引入了判斷機制,我們編譯之後的代碼不能再像之前那樣像一條串似的直接拼接起來。我們在第一篇中編譯後的代碼大概類似於這樣:return 'H1!'+it.name;可是,我們只進行了判斷,沒有進行字元串拼接的話,代碼大概是這樣:

return if(it.name){
    'Hi!'+it.name;
}

 

連語法都不正確了啊喂!不要慌,總之先冷靜下來找時光機。。。啊不對,是先回想正常情況下我們是如何完成類似的拼接的:

var out="";
 
if(it.name){
    out += 'Hi!'+it.name;
}
 
return out;

因此類似的,我們要引入一個變數out,這樣我們就能在判斷體內把結果拼接起來了。於是,我們要替換的目標變成了這樣:

標記 結果
{{? it.name }} => '; if( it.name ){ out += '
{{?? it.age === 0}} => '; } else if( it.age === 0 ) { out += '
{{??}} => '; } else{ out += '
{{?}} => '; } out += '

我們能這麼做的前提,是我們假設,在進行判斷語句之前,這個字元串還沒有結束。 於是,我們加上單引號使其提前結束(我們使用單引號來標記字元串,還記得嗎?)在執行完判斷之後,我們又通過out+='來繼續拼接字元串。也就是說,在執行判斷之前,我們的字元串是未結束的狀態,在執行完判斷之後,我們的字元串依然是未結束的狀態

實現過程

好了,剩下的就只有將剛剛的思考轉化為實際代碼的過程了,我建議你自己手動完成這部分,如果你實在不知如何下手的話,這裡有一份代碼供你參考:

點擊這裡直接運行試試

HTML:

<div id="target"></div>
 
<script type="text/x-dot-template" class="js-template">
{{? it.name }}
<div>嗨, {{= it.name}}!</div>
{{?? it.age === 0}}
<div>我猜應該還沒人給你起名字吧?</div>
{{??}}
<div>你已經 {{= it.age}} 歲了但是你還沒有名字?</div>
{{?}}
</script>
View Code

 

JavaScript(需要先引入jQuery):

var jst = {};
 
var VALUE = /\{\{\=(.*)\}\}/g;
 
var IF = /\{\{\?([^\?]{1}.*?)\}\}/g;
//var IF = /\{\{\?([^\?]+.*?)\}\}/g;
var ELSE_IF = /\{\{\?\?(.+?)\}\}/g;
var ELSE = /\{\{\?\?\}\}/g;
var END_IF = /\{\{\?\}\}/g;
 
 
jst.template = function(templateText) {
 
    // ↓這個就是實際運行的模板函數
    return function(it) {
        // 值綁定
        // var result = templateText;
        var result = templateText.replace(VALUE, "'+($1)+'");
        var ev = result;
 
        // if && else
        // 這裡是為了把字元 if else 裡面的內容提取出來
        ev = ev.replace(IF, "'; if(($1)){out +=' ")
            .replace(ELSE, "'}else{out += ' ")
            .replace(ELSE_IF, "';}else if(($1)){ out += ' ")
            .replace(END_IF, "'}; out+=' ");
 
        ev = "var out = ''; out+='  " + ev.split('\n').join("") + "' ;";
 
        //console.log(ev);
        // debugger
        return eval(ev);
    }
}
 
    //運行部分:
    var func = jst.template($('.js-template').html());
 
    $('#target').html(func({
        name:'十一川',
        age:0
    }));
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.Dubbo是什麼? Dubbo是一個分散式服務框架,致力於提供高性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。簡單的說,dubbo就是個服務框架,如果沒有分散式的需求,其實是不需要用的,只有在分散式的時候,才有dubbo這樣的分散式服務框架的需求,並且本質上是個服務調用的東東,說 ...
  • 之前在講表拆分的時候氛圍垂直拆分和水平拆分 垂直拆分的查詢其實不難,就是從單表變為了多表,而大部分情況下只是對主表的查詢多,從表的查詢會很少用到,這樣的情況下關聯查詢不需要太多的考慮 水平拆分之前講了大數據量的情況下根據歷史時間來查詢,那麼今天來說另外一種,還有一隻是根據主鍵id取模後根據這樣的規則 ...
  • 參考:http://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/builder.html ...
  • 轉載請標明原文地址:http://www.cnblogs.com/zhangyukof/p/6829538.html 隨著編程經驗的積累,我對編程的理解也不斷的發生變化。最開始學的是演算法,然後是數據結構,現在開始學習編程思想,這是一個不斷進步的過程。編程思想可能是最基礎但卻是最重要的,以前對這些概念 ...
  • 一.簡介 ZK的安裝和配置十分簡單,既可以配置成單機模式,也可以配置成集群模式,zk使用java編寫的運行在java環境上,3個ZK服務進程是建議的最小進程數量,而且建議部署在不通的物理機上面,減少宕機帶來的風險。 二.下載並解壓 http://www.apache.org/dyn/closer.c ...
  • 收錄待用,修改轉載已取得 "騰訊雲" 授權 前言 在 web 前端開發中,我們會藉助 Grunt、Gulp 和 Webpack 等工具的 Watch 模塊去監聽文件變化,那服務端應該怎麼做?其實文件變化的監聽依然可以藉助構建工具,但我們還需要自動重啟服務或者熱重載。本文將介紹三種常見的方法。 方案一 ...
  • 收錄待用,修改轉載已取得 "騰訊雲" 授權 作者:kurtshen ES6 新增了幾種集合類型,本文主要介紹Set以及其使用。 其基本描述為 Set對象是值的集合,你可以按照插入的順序迭代它的元素。 Set中的元素只會出現一次,即 Set 中的元素是唯一的。 它的聲明 new Set([iterab ...
  • JavaScript面向對象的理解 筆記鏈接: http://pan.baidu.com/s/1c0hivuS 1:JavaScript 中分兩種對象,函數對象和普通對象new Function() 創建的對象都是函數對象、其他的都是普通對象。函數對象 例: 普通對象 例: 2:原型對象 JavaS ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...