4,VTemplate模板引擎的使用--進階篇

原文地址:https://www.cnblogs.com/kingthy/archive/2009/09/03/net-vtemplate-doc-3.html

1、<vt:template>與<vt:include>標籤的不同

<vt:template>和<vt:include> 標籤都包含file屬性,如果這兩個標籤都設置file屬性,那這兩個標籤看起來很相似,並且最終效果都是將文件的內容包含進來。但是對於模板引擎來說它們之間的差別卻是非常的大。

<vt:template>標籤是“模板塊”標籤,它能擁有自己的“變量”,它會成爲它內部的標籤的“宿主模板”(OwnerTemplate)。而<vt:include>則只是簡單的將文件內容包含進來,它內部的標籤的“宿主模板”與它相同。

現假如有一個VT模板文件: inc_content.html

我是包含文件裏的變量 {$:#.var1}。
我是包含文件裏的foreach標籤:
<vt:foreach from=”$#.names” item=”#.name” index=”#.i”>
包含文件的第{$:#.i}個名字叫{$:#.name}。
</vt:foreach>

現分別用<vt:template> 和 <vt:include>標籤去包含上面的文件,如下:

A、<vt:template>包含:

我是外部的變量{$:#.var1}。
我是外部的foreach標籤:
<vt:foreach from=”$#.names” item=”#.name” index=”#.i”>
外部的第{$:#.i}個名字叫{$:#.name}。
</vt:foreach>
<vt:template id=”inc” file=”inc_content.html” />


B、<vt:include>包含:

我是外部的變量{$:#.var1}。
我是外部的foreach標籤:
<vt:foreach from=”$#.names” item=”#.name” index=”#.i”>
外部的第{$:#.i}個名字叫{$:#.name}。
</vt:foreach>
<vt:include id=”inc” file=”inc_content.html” />


上面兩塊的VT模板代碼看起來很相似,但是經解析後A中的var1與inc這個<vt:template>模板塊下的變量var1分別獨立存在,互不影響!而B中的變量var1與inc這個<vt:include>的變量var1相等,都是引用同一個變量(其它變量類似)。

現假如A、B兩塊的VT模板代碼都通過過下面的程序來處理:

this.Document.Variables.SetValue("var1", 1);
this.Document.Variables.SetValue("names", new string[] { "張三", "李四", "王五" });


也即是隻對外部變量var1names賦值,最終經模板引擎解析輸出後,它們的輸出結果如下:
vtemplate_3_snap_1

從圖可知,<vt:template>包含的沒有數據輸出,而用<vt:include>包含則有數據輸出並且和外部數據一模一樣!所以可把<vt:template>標籤看成是程序語言裏的,它能擁有它自己的變量,改變外部變量的值不會影響到其內部的同名變量,並且外部標籤可通過其id獲取其內部變量

具體的示例代碼,請參考:http://net-vtemplate.googlecode.com/svn/src/VTemplate.WebTester/template_include_test.ashx.cs

 

 

2、使用變量表達式

變量表達式可用在標籤屬性,也可用在變量元素中。它的作用就是用於獲取變量中某個字段、屬性、函數方法或索引的結果值。比如上例中的#.var1就是說明獲取var1變量的值,也即是數值“1”。

對於變量值類型中真實存在的字段、屬性或函數方法,VT模板引擎將通過反射獲取其結果值,例如以下VT模板代碼:

我叫{$:user.name},今年{$:user.age}歲,我來自{$:user.location.getcity()}


假如對user變量賦以下類實例的值,那麼上面模板代碼解析時模板引擎將能正確解析出各個變量表達式的最終值。

class Location
{   
    public string GetCity(){
         //code here
    }
}

class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Location Location { get; set; }
}

但在某些情況下,我們需要獲取的“值”並不簡單地存在變量值的類型中,而是需要經過其它處理運算得出來的值。比如上面的獲取個人資料裏,我們還要獲取用戶的個人財產總額,但從上面的代碼裏可看出個人財產總額項並不存在於User類裏,所以導致VT模板引擎根本無法獲取此項的值。那我們要如何做才能獲取此項數據呢?VT模板引擎提供了一個手動設置變量表達式的值的方法,而我們要做的就是根據此方法手動設置變量表達式的值!例如上面的VT模板代碼改爲如下:

我叫{$:user.name},今年{$:user.age}歲,我來自{$:user.location.getcity()},我的個人財產總共有{$:user.totalmoney}元。

從上面的類實例代碼中可知道totalmoney這個項是不存在User的屬性/字段列表裏的,所以我們就要手動設置{$:user.totalmoney}的值,示例代碼如下:

/// <summary>
/// 返回某個用戶的個人財產總額
/// </summary>
/// <param name="user"></param>
/// <returns></returns>

static int GetUserTotalMoney(User user)
{
    //code here
}

//------------------------使用代碼----------------------------------------//

//獲取user變量
Variable userVar = this.Document.Variables["user"];
//生成User實例
User user = new User();
//…………其它代碼略去…………//
//設置user變量的值爲User實例
userVar.Value = user;
//手動設置totalmoney的值(注意,這行和上面那行的順序不能搞亂)
userVar.SetExpValue("totalmoney", GetUserTotalMoney(user));

 

 

3、有條件的控制數據的輸出

在輸出數據時,我們並不是簡單的輸出所有數據,而是要根據外部的許多條件組合獲取其中的部分數據。而對於這些外部條件,如果可固定的則我們可以在設計VT模板時將其寫入到標籤(建議是<vt:template>標籤)的屬性裏,這樣我們就能在程序代碼裏獲取到這些外部條件並加以處理數據

例如博客園的新聞頻道裏右邊的“相關新聞”、“熱點新聞”兩欄數據,如下圖:

vtemplate_3_snap_2

假設“相關新聞”裏獲取的新聞是屬於"relating”類型的新聞,而“熱點新聞”則是獲取屬於"hoting”類型的新聞,則我們可以設計其VT模板如下:

<div class="side_block">
  <h3 class="title_blue">相關新聞</h3>
  <vt:template name="topnewstype="relating" file="cnblogs_newsdata.html" />
</div>
<div class="side_block">
  <h3 class="title_yellow">熱點新聞</h3>
  <vt:template name="topnewstype="hoting" file="cnblogs_newsdata.html" />
</div>

在上面的VT模板中,定義了兩個name爲"topnews”的<vt:template>標籤,這是爲了便於在代碼裏對這兩個<vt:template>進行統一處理(因爲它們要處理的數據都是相同,只是獲取數據條件不同)而定義的名稱。並且分別定義了自定義屬性type用於做數據獲取條件。其中包含文件cnblogs_newsdata.html的VT模板如下:

<ul class="topnews block_list bt">
  <vt:foreach from="$#.newsdata" item="#.news" index="#.i" id="newslist">
  <li>
    <a href="{$:#.news.url}" title="{$:#.news.title htmlencode='true'}">{$:#.news.title htmlencode='true'}...</a>
  </li>
  </vt:foreach>
</ul>

在此文件的VT模板中,定義了一個id爲"newslist"的<vt:foreach>標籤,定義此id是爲了在程序代碼裏控制新聞的輸出和處理每條新聞的訪問地址,也即是"{$:#.news.url}”變量表達式的值。

示例代碼:

//獲取所有名稱爲topnews的模板塊
ElementCollection<Template> templates = this.Document.GetChildTemplatesByName("topnews");
foreach (Template template in templates)
{
    //根據模板塊裏定義的type屬性條件取得新聞數據
    List<News> newsData = GetNewsData(template.Attributes.GetValue("type"));
    //設置變量newsdata的值
    template.Variables.SetValue("newsdata", newsData);

    //取得模板塊下Id爲newslist的標籤(也即是在cnblogs_newsdata.html文件中定義的foreach標籤)
    Tag tag = template.GetChildTagById("newslist");
    if (tag is ForEachTag)
    {
        //如果標籤爲foreach標籤則設置其BeforeRender事件用於設置變量表達式{$:#.news.url}的值
        tag.BeforeRender += (sender, e) =>
        {
            ForEachTag t = (ForEachTag)sender;
            //取得當前項的值(因爲foreach標籤的數據源是List<News>集合,所以當前項的值類型爲News實體)
            News news = (News)t.Item.Value;
            //設置當前項的變量表達式的值.也即是"{$:#.news.url}"變量表達式
            t.Item.SetExpValue("url", GetNewsUrl(news));
        };
    }
}

在上面代碼中使用了BeforeRender事件,此事件是在標籤元素的數據呈現之前觸發。對於循環元素<vt:foreach>和<vt:for>,因爲每次循環時都會呈現數據,也就導致每次循環時都會觸發此事件(包括AfterRender事件),所以我們就可通過此事件方法獲取到循環當前項的值。

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