ASP.NET MVC视图引擎SPARK文档中文版
一,前言
????? 寫個前言還是不錯的,可以先讓大家看看這個文章是個大體什么內(nèi)容,然后打醬油的打醬油,路過的繼續(xù)路過,但相信停下來總有些許收獲。
????? 很久沒有寫東西,一個最近挺忙,二個好像沒有什么特別好的內(nèi)容好寫,三個沒有什么很好的心得與大家分享。最近一個項目前臺使用MVC,用到了SPARK引擎,感覺灰常好用,不敢私藏,拿出來給大家分享一下,而又因為關(guān)于SPARK的中文資料簡直可以說是沒有,所以這篇大家可以認為是翻譯,只是翻譯水平比較差點,大家湊合了,如果有高手指出不足最好了,拋磚引玉了。
????? ASP.NET?MVC 現(xiàn)在已有四種主要的視圖引擎:Spark、NHaml、Razor和傳統(tǒng)的ASPX文件模板,Razor是新生事物,傳統(tǒng)的ASPX文件模板做過MVC的大體都有了解和應(yīng)用了,而Spark和NHaml似乎用得不是很多,很有可能是中文資料欠缺,導(dǎo)致連了解的都不多。本人是在搜索關(guān)鍵詞ASP.NET MVC SPARK,百度和GOOGLE都是一篇:《ASP.NET MVC的四種視圖引擎》,文章只是粗略的寫了一下各個視圖的特點,確實是讓大家有了一點點的了解。
????? 本文基本上算是Spark官方文檔的翻譯,其網(wǎng)址是:http://sparkviewengine.com/documentation,最近網(wǎng)絡(luò)河蟹亂爬,如果打不開,請大家自行FQ!
?
二,將Spark加載到Asp.Net MVC中
Spark引擎不被controller管理,最簡單的方法是在Asp.Net MVC web應(yīng)用程序中將SparkViewFactory在Global Application_Start中注冊,如:
protected void Application_Start(object sender, EventArgs e)
{
??? ViewEngines.Engines.Add(new SparkViewFactory());
}
這也是注冊其它非默認視圖引擎的方法
?
三,Spark配置
1,web.config中的配置
所有的spark配置都包括在<spark>標簽中,如:
<!--增加spark配置名-->
<configSections>
? <section name="spark" type="Spark.Configuration.SparkSectionHandler, Spark"/>
</configSections>
<!--spark配置主體-->
<spark>
? <compilation debug="true|false" defaultLanguage="Default|CSharp|VisualBasic">
??? <assemblies>
????? <add assembly="YourAssemblyName" />
????? <add assembly="YourOtherStrongAssemblyName, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
??? </assemblies>
? </compilation>
? <pages automaticEncoding="true|false" pageBaseType="Your.NonDefault.BaseSparkView" prefix="{optional string}">
??? <namespaces>
????? <add namespace="System"/>
????? <add namespace="System.Collections.Generic"/>
????? <add namespace="System.Linq"/>
????? <add namespace="System.Web.Mvc"/>
??? </namespaces>
??? <resources>
????? <add match="/content/css" location="http://www.yourcdnprovider.com/youraccount/allstyles/css"/>
????? <add match="/content/js" location="http://www.yourcdnprovider.com/youraccount/appname/js"/>
??? </resources>
? </pages>
</spark>
自動解碼最好是true,這將會對每個使用${expr}的操作符都進行HTML encoding,而使用方法!{expr}將避免被解碼
resources區(qū)域用于控制形如”~/“樣式的鏈接,如:<script src="~/content/js/foo.js"/>,將會被解析成給定的location+"/foo.js",對于使用靜態(tài)文件或CDN來說是非常有意義的。
2,也可以在Application_Start中配置,如:
protected void Application_Start(object sender, EventArgs e)
{
??? var settings = new SparkSettings()
??????? .SetDebug(true)
??????? .SetPageBaseType("Your.NonDefault.BaseSparkView")
??????? .AddAssembly("YourAssembly")
??????? .AddNamespace("System")
??????? .AddNamespace("System.Collections.Generic")
??????? .AddNamespace("System.Linq")
??????? .AddNamespace("System.Web.Mvc");
?
??? ViewEngines.Engines.Add(new SparkViewFactory(settings));
}
?
四,常規(guī)語法
1,包含代碼
可以使用包括C#代碼,任何helper方法,對象屬性或返回非空值的表達式,如:
<p>${"Hello world"}</p>
<p>${Guid.NewGuid().ToString("n")}</p>
代碼可以表現(xiàn)為特殊的html標簽或其屬性,如"if","else"和"var",在這些代碼的區(qū)域中將不需要使用${},如:
<var names="new [] {'alpha', 'beta', 'gamma'}"/>
<for each="var name in names">
? <test if="name == 'beta'">
??? <p>beta is my favorite.</p>
??? <else/>
??? <p>${name} is okay too I suppose.
? </test>
</for>
但如果你想輸出一個普通標簽的屬性時,標記符號還是需要加上的,如:
<viewdata currentProduct="Product"/>
<p>${currentProduct.Name} <a href="/Product/Edit/${currentProduct.Id}">Edit</a></p>
2,代碼中的特殊字符
可以使用所有的C#代碼,但是請小心使用,確保你的商業(yè)邏輯都寫在你的controller或其它代碼中
只有很少一部分的代碼需要使用特殊的方法去避免被錯誤解析,如使用[[和]]代替<>,另外,在屬性中如果使用了雙引號,那么屬性中如果使用了spark語法的字符型值時,則需要使用單引號;如果使用單個char常量,使用(char)'x'代替"x",如:
<viewdata products="IList[[Products]]"/>
<var styles="new[] {'even', 'odd'}"/>
3,配置使用Spark前綴
默認情況下,Spark標簽是不需要其它特殊標記的,但是當使用Spark生成xml或xhtml時,配置spark前綴就有必要了,方法如下:
<spark>
? <pages prefix="s"/>
</spark>
Or
var settings = new SparkSettings()
??? .SetPrefix("s");
當配置了前綴時,每個spark標簽或?qū)傩远夹枰郧熬Y開頭,以被spark引擎識別,而spark內(nèi)置的標簽如macro:,content:,use:和section:不需要加前綴,如:
<div>
? <s:viewdata user="UserInfo"/>
? <p s:if="user != null">${user.Name}</p>
? <s:LoginForm/>
</div>
4,引入xmlns namespaces至Spark標簽中
這個不是太好理解,直接上例子:
<html xmlns="http://www.w3.org/1999/xhtml"
????? xmlns:s="http://sparkviewengine.com/"
????? xmlns:fn="http://sparkviewengine.com/macro/">
<body>
? <fn:ShowNames favorite="string">
??? <s:var names="new [] {'alpha', 'beta', 'gamma'}"/>
??? <s:for each="var name in names">
????? <s:test if="name == favorite">
??????? <p>${favorite} is my favorite.</p>
??????? <s:else/>
??????? <p>${name} is okay too I suppose.
????? </s:test>
??? </s:for>
? </fn:ShowNames>
? ${ShowNames("beta")}
? ${ShowNames("gamma")}
</body>
</html>
?
五,變量
1,聲明局部變量
使用”var“標簽可以簡單快速的聲明局部變量,默認的行為將會是生成一個有初始值的局部動態(tài)變量類型”var“,如:
<var styles="new [] {'odd', 'even'}" i="0"/>
將產(chǎn)生如下:
var styles = new [] {"odd", "even"};
var i = 0;
”var“標簽有一個”type“屬性,可以指明變量的類型,如:
<var foo="null" bar="null" type="string"/>
將產(chǎn)生如下:
string foo = null;
string bar = null;
最后,如果”var“標簽沒有在一個以”/>“結(jié)尾的標簽內(nèi)聲明,變量將會有一個作用域,作用域以”</var>“結(jié)束,在作用域外不將不能對變量進行賦值,如:
<div>
? <var styles="new [] {'even', 'odd'}" i="0">
??? <p>${i} is ${styles[i%2]}</p>
? </var>
? <set i="5"/> <!-- compiler error - variable i is out of scope -->
</div>
將產(chǎn)生如下:
Output.Write("<div>");
{
var styles=new[] {"even", "odd"};
var i = 0;
Output.Write("<p>");
Output.Write(i);
Output.Write(" is ");
Output.Write(styles[i%2]);
Output.Write("</p>");
}
Output.Write("</div>");
i = 5;
2,聲明全局變量
局部變量有其作用域,而全局變量可以在view,master或局部模板文件中聲明,其值可以在任何地方使用,如:
<h2>${Title}</h2>
<global Title="'My Default Title'"/>
注意到其值是以雙引號包圍,內(nèi)部還有單引號(可以理解為雙引號是因為HTML標簽屬性值要以雙引號包含,而內(nèi)部是string類型,用單引號避免外部雙引號重復(fù)使用)
全局變量實際上將會以視圖類中的一個字段成員執(zhí)行,所以上面例子中將將產(chǎn)生一個object Title="My Default Title"的字段成員,任何方法都可以引用這個變量,spark仍然提供一個”type“屬性聲明具體類型以避免使用object類型,另外,多個變量可以聲明要同一個標簽中,如:
<global type="string" Foo="'Hello'" Bar="'World'" />
3,設(shè)置局部和全局變量的值
${expr}和其它語法只是用于輸出值,局部或全局變量的賦值需要使用”set“標簽,如:
<html>
? <head>
??? <global type='string' Title='"Site Name"'/>
??? <title>${Title}</title>
? </head>
? <body>
??? <div><use content="view"/></div>
? </body>
</html>
在視圖中設(shè)置Title的值
<set Title='product.Name + " - " + Title'/>
<!-- or -->
<set Title='string.Format("{0} - {1}", product.Name, Title)'/>
4,使用view data
ViewData作為一個對象字典可以使用形如${ViewData["blah"]}來使用,但是建議使用一個強類型的ViewData將會使操作更為簡便,如:
<viewdata
? Caption="string"
? Products="System.Collections.Generic.IList[[MyApp.Models.Product]]"/>
<div>
? <h3>${Caption}</h3>
? <div? each="var product in Products">
??? <h4>${product.Name}</h4>
??? <div>${product.Description}</div>
? </div>
</div>
ViewData標簽可以聲明在view中或是master文件中,結(jié)果都是一樣的,如:
string Caption
{get {return (string)ViewData["Caption"];}}
System.Collections.Generic.IList<MyApp.Models.Product> Products
{get {return (System.Collections.Generic.IList<MyApp.Models.Product>)ViewData["Products"];}}
在這種情況下,需要使用[[and]]來代替<and>
5,使用view data中的確定類型的model
在view或master文件中viewdata可能有一個model的屬性
<viewdata model="MyApp.Models.Catalog"/>
<p>(${ViewData.Model.CatalogID}) ${ViewData.Model.Name} </p>
model的屬性可以和其它viewdata中的變量聲明共同使用,例如在master文件中使用了一個<viewdata Title="string"/>,在view中仍然可以使用含有一個Title屬性的string字段的model,<viewdata model="typename"/>
<viewdata Title="string"/>
<title>${Html.Encode(Title ?? "My Sample MVC Application")}</title>
這一段不好理解,建議大家可以看看英文原文
?
六,表達式
1,簡單的C#表達式
可以使用${expr}或<%=expr%>
例:
<div>
? <p>The time is ${DateTime.Now}.</p>
? <p>The time is <%=DateTime.Now%>.</p>
</div>
2,Nulls表達式
當使用簡單的C#表達式時,如果值為null時,將會輸出錯誤,此時可以使用$!{expr}來避免輸出錯誤,只是輸出空值
<div class="shipto">
? <p>$!{currentInvoice.ShipTo.FullName}</p>
? <p>$!{currentInvoice.ShipTo.Address.City}, $!{currentInvoice.ShipTo.Address.State} $!{currentInvoice.ShipTo.Address.Zip}</p>
</div>
如果是currentInvoice為null或ShipTo為null時,將會輸出如下:
<div class="shipto">
? <p></p>
? <p>,? </p>
</div>
這個主意不是太好,不過總比一個亂碼錯誤頁好許多,所以確定你的值100%不為空吧
3,使用MVC helpers
可以使用HtmlHelper,UrlHelper和AjaxHelper
<!-- Link to the Sort action on the current controller -->
<p>${Html.ActionLink("Click me", "Sort")}</p>
<!-- Put out data in a way that's safe -->
<p>${Html.Encode(stuff)}</p>
4,條件標簽:if,test和else
使用例子說明:
例1:
<var x='5'/>
?
<if condition='x == 5'>
? <p class='resultmessage'>Some value is five</p>
</if>
例2:
<viewdata user='UserInfo'/>
?
<if condition='!user.IsLoggedIn()'>
? <p>Here's a login form</p>
</if>
<else if='user.HasRole(RoleType.Administrator)'>
? <p>Hello - you're an admin</p>
</else>
<else if='user.HasRole(RoleType.Registered)'>
? <p>Hello - you're a registered user</p>
</else>
<else>
? <p>I have no idea what type of person you are</p>
</else>
例3:
可以使用<test if="">語法來代替<if condition="">語法,<else if=""/>和<else/>來代替分散標簽
<viewdata user='UserInfo'/>
?
<test if='!user.IsLoggedIn()'>
? <p>Here's a login form</p>
? <else if='user.HasRole(RoleType.Administrator)'/>
? <p>Hello - you're an admin</p>
? <else if='user.HasRole(RoleType.Registered)'/>
? <p>Hello - you're a registered user</p>
? <else/>
? <p>I have no idea what type of person you are</p>
</test>
5,使用if和elseif判斷屬性或標簽顯示
if和elseif可以使用在任何標簽中
例1:
<var x='5'/>
<p if='x==5' class='resultmessage'>Some value is five</p>
例2:
<use namespace='SampleApp.Models'/>
<viewdata user='UserInfo'/>
?
<p if='!user.IsLoggedIn()'>Here's a login form</p>
<p elseif='user.HasRole(RoleType.Administrator)'>Hello - you're an admin</p>
<p elseif='user.HasRole(RoleType.Registered)'>Hello - you're a registered user</p>
<else>
? <p>I have no idea what type of person you are</p>
</else>
6,一次判斷
在頁面中只需要調(diào)入一次某個資源,如css文件或jquery,可標簽中使用once="flagname"還指明,你當然可以使用${expr}或其它語法來為flagname賦值,實際上在spark文件的任何地方都可以使用這樣的表達式
<content name="head">
? <!--? add jquery if it hasn't been yet, and add countdown plugin -->
? <script once="jquery" type="text/javascript" src="~/content/js/jquery-1.2.6.js"/>
? <script once="jquery-countdown" type="text/javascript" src="~/content/js/jquery.countdown.js"/>
</content>
這里不是太明白
7,有條件的屬性輸出
使用?{boolean}表達式只能用在屬性值中,例:
<ul>
? <li each="var product in Products" class="first?{productIsFirst} last?{productIsLast}">
??? ${H(product.Name)}
? </li>
</ul>
將會輸出
<ul>
? <li class="first">Alpha</li>
? <li>Beta</li>
? <li>Gamma</li>
? <li class=" last">Delta</li>
</ul>
or
<ul>
? <li class="first last">just one product</li>
</ul>
如果屬性值為空,那么將表現(xiàn)如下:
<input type="checkbox" name="chkhello" checked="?{isHelloChecked}"></input>
將會輸出
<input type="checkbox" name="chkhello" checked=""></input>
or
<input type="checkbox" name="chkhello"></input>
8,循環(huán)
一個foreach循環(huán)包含標簽for和each屬性,each屬性值必須包含類型,變量名,關(guān)鍵字"in"和循環(huán)體(collection),如:
<viewdata Posts="IList[[MyApp.Models.Post]"/>
<for each="var post in Posts">
? <p>${post.Title}</p>
</for>
任何一個循環(huán)都有Index,Count,IsFirst和IsLast屬性,在循環(huán)作用域內(nèi)有效,而且只有被使用了才會生成,如:
<viewdata Posts="IList[[MyApp.Models.Post]"/>
<var styles="new[] {'even','odd'}"/>
<for each="var post in Posts">
? <p class="${styles[postIndex%2]}">${postIndex}. ${post.Title}</p>
</for>
在循環(huán)時,如果使用了Count或IsLast變量,spark將會使用IEnumerable<T>的Linq方法后,使用Count()取得,而舊的spark引擎會先循環(huán)一次以取得count,所以使用Count和IsLast時,請注意性能問題
以下是局部變量和循環(huán)的復(fù)雜使用
<viewdata currentProductId="int"/>
<var styles="new [] {'even', 'odd'}" isCurrent="false">
? <for each="var product in Products" isCurrent="product.Id==currentProductId">
??? <p class="highlighted?{isCurrent} ${styles[productIndex%2]}">${Html.Encode(product.Name)}</p>
? </for>
</var>
9,在標簽屬性中使用循環(huán)
例1:
<table>
? <tr>
??? <td>Name</td>
??? <td>Type</td>
? </tr>
? <tr each='var user in users'>
??? <td>${user.Name}</td>
??? <td>${user.UserType}</td>
? </tr>
</table>
例2:
<table>
? <tr>
??? <td>Name</td>
??? <td>Type</td>
? </tr>
? <var classes="new [] {'even','odd'}">
??? <tr each="var user in users" class="${classes[userIndex%2]}">
????? <td>${userIndex}) ${user.Name}</td>
????? <td>${user.UserType}</td>
??? </tr>
? </var>
</table>
10,使用命名空間
<use namespace="System.Collections.Generic"/>
<use namespace="System.Web.Mvc"/>
<viewdata Names="IList[[string]]"/>
不好說明
11,內(nèi)置代碼
使用”#“符號聲明當前行為C#代碼,如:
<test if="user.IsLoggedIn()">
? <p>Hello, ${user.Name}.</p>
? <else if="user.HasValidTrialSession()"/>
? <p>Hello, Valued Future Customer.</p>
? <else/>
? <p>Hello, er... you.</p>
? # System.Diagnostic.Trace.WriteLine("Unexpected anon user.");
? # if (System.Diagnostic.Debugger.IsAttached)
? #?? System.Diagnostic.Debugger.Break();
</test>
這里需要說明的是spark變量和C#變量是可以通用的!
12,聲明宏
當需要一個helper方法時,如需要輸入一些參數(shù)和返回一個字符串時,<macro>就可以做這些事情了,聲明時使用形如<macro name="foot">,然后使用時用${foo()}或<%=foo()%>,例:
<viewdata errorMessage="string" />
?
<macro name="ShowError" caption="string" message="string">
<div class="message error">
? <h3>${H(caption)}</h3>
? <div>${message}</div>
? <% Logger.Warn(caption); %> <!-- this is a MR example. asp.net mvc would use different logging -->
</div>
</macro>
?
<h2>Place Order</h2>
<test if="!string.IsNullOrEmpty(errorMessage)">
? ${ShowError("Failed to place order", errorMessage)}
</test>
將會產(chǎn)生如下:
string ShowError(string caption, string message)
{
? using(OutputScope(new System.IO.StringWriter()))
? {
??? Output.Write("\r\n? <div class=\"message error\">\r\n??? <h3>");
??? Output.Write(H(caption));
??? Output.Write("</h3>\r\n??? <div>");
??? Output.Write(message);
??? Output.Write("</div>\r\n??? ");
??? Logger.Warn(caption);
??? Output.Write("? </div>\r\n");
??? return Output.ToString();
? }
}
?
//... and in the RenderViewContent method
Output.Write("\r\n<h2>Place Order</h2>\r\n");
if (!string.IsNullOrEmpty(errorMessage))
{
? Output.Write(ShowError("Failed to place order", errorMessage));
} // if (!string.IsNullOrEmpty(errorMessage))
Output.Write("\r\n\r\n<!-- form here, field validation messages, etc. -->\r\n\r\n");
轉(zhuǎn)載于:https://www.cnblogs.com/zhaoyx/articles/1890218.html
總結(jié)
以上是生活随笔為你收集整理的ASP.NET MVC视图引擎SPARK文档中文版的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于LGame-0.2.9版的开发进度
- 下一篇: WPF示例连接