兩者皆可包含外部檔案,但 變數作用域機制截然不同:
| 特性 | <vt:template> | <vt:include> |
|---|---|---|
| 變數隔離 | ✅ 擁有獨立變數空間,外部同名變數互不干擾 | ❌ 共享同一變數空間,引用相同變數實例 |
| 宿主模板 | 成為內部標籤的 OwnerTemplate | 內部標籤宿主與外部相同 |
| 類比概念 | 類別 (Class):封裝狀態與行為 | 檔案包含 (Include):單純文字插入 |
| 外部存取內部變數 | 可透過 template.Variables 存取 | 不可區分,為同一變數 |
我是外部變量 {$:#.var1}
<vt:foreach from="#.names" item="name" index="i">
外部第 {$:#.i} 個名字叫 {$:#.name}
</vt:foreach>
<vt:template id="inc" file="inc_content.html" />
<vt:include id="inc" file="inc_content.html" />
若僅對外部 var1=1, names=[張三,李四] 賦值:
當模板需顯示的屬性不存在於實體類別 (如「個人財產總額」需即時計算) 時,使用 Variable.SetExpValue:
// 模板中使用:{$:user.totalmoney}
// 實體類別無 totalmoney 屬性
Variable userVar = doc.Variables["user"];
User user = GetUserFromDb(); // 取得實體
userVar.Value = user; // 1. 先設定實體值
// 2. 手動設定運算式值 (順序不可顛倒)
userVar.SetExpValue("totalmoney", CalculateTotalMoney(user));
案例:部落格側邊欄顯示「相關新聞」與「熱門新聞」,資料來源相同但篩選條件不同。
<div class="side_block">
<h3>相關新聞</h3>
<vt:template name="topnews" type="relating" file="news_list.html" />
</div>
<div class="side_block">
<h3>熱門新聞</h3>
<vt:template name="topnews" type="hoting" file="news_list.html" />
</div>
<ul class="topnews">
<vt:foreach from="#.newsdata" item="news" index="i" id="newslist">
<li><a href="{$:#.news.url}" title="{$:#.news.title}">{$:#.news.title}...</a></li>
</vt:foreach>
</ul>
// 1. 取得所有名為 "topnews" 的模板塊
var templates = doc.GetChildTemplatesByName("topnews");
foreach (Template tpl in templates)
{
// 2. 依標籤屬性 type 取得不同篩選條件的資料
string type = tpl.Attributes.GetValue("type"); // "relating" 或 "hoting"
List newsData = GetNewsByType(type);
// 3. 設定該模板塊區域變數
tpl.Variables.SetValue("newsdata", newsData);
// 4. 取得 foreach 標籤,掛上 BeforeRender 事件動態產生 URL
var tag = tpl.GetChildTagById("newslist");
if (tag is ForEachTag foreachTag)
{
foreachTag.BeforeRender += (sender, e) =>
{
var currentNews = (News)((ForEachTag)sender).Item.Value;
// 動態設定 {$:#.news.url} 運算式值
((ForEachTag)sender).Item.SetExpValue("url", GenerateNewsUrl(currentNews));
};
}
}
vt:template 方便批次處理,自訂屬性 type 傳遞業務參數。vt:template 擁有獨立 Variables,互不干擾。