This is another in a series of posts I'm doing that cover some of the new ASP.NET MVC 3 features:
- New @model keyword in Razor (Oct 19th)
- Layouts with Razor (Oct 22nd)
- Server-Side Comments with Razor (Nov 12th)
- Razor's @: and <text> syntax (Dec 15th)
- Implicit and Explicit code nuggets with Razor (today)
这是我手头上正在写的另一个系列里的一个帖子,这个系列主要是想全面地介绍一下ASP.NET MVC 3的特性:
- Razor的新关键字@model(10月19号)
- Razor的布局(10月22号)
- Razor的服务器端评论(11月12号)
- Razor的"@:"和"<text>"语法(12月15号)
- Razor的隐式和显示代码嵌入块(今天)
In today's post I'm going to discuss how Razor enables you to both implicitly and explicitly define code nuggets within your view templates, and walkthrough some code examples of each of them.
在今天的帖子,我将会讨论一下在Razor下,通过View模板怎么隐式和显式使用代码嵌入,并对其中的每个方面给出代码的例子。
Fluid Coding with Razor
ASP.NET MVC 3 ships with a new view-engine option called "Razor" (in addition to the existing .aspx view engine). You can learn more about Razor, why we are introducing it, and the syntax it supports from myIntroducing Razor blog post.
ASP.NET MVC 3 搭载了一个叫做"Razor"的可选视图引擎(除.aspx视图引擎之外)。你也可以从我博客里的Razor介绍帖子里了解到Razor的更多内容、为什么要引进这个视图引擎和它支持什么样的语法。
Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow. Unlike most template syntaxes, you do not need to interrupt your coding to explicitly denote the start and end of server blocks within your HTML. The Razor parser is smart enough to infer this from your code. This enables a compact and expressive syntax which is clean, fast and fun to type.
Razor最小化了在编写视图模板时代码量和敲击键盘数,并且支持快速流畅的编程。与大多数的语法不同,在HTML中编码时不需要明确指定服务器代码块的开头和结尾。Razor解析器很智能,可以自动识别出来。这样使得语法紧凑而具有表现力,也使得代码干净快速,以及在写代码时充满乐趣。
For example, the Razor snippet below can be used to iterate a collection of products and output a <ul> list of product names that link to their corresponding product pages:
例如,以下摘录的Razor代码遍历一个集合,输出一个展示产品名称的无序列表,每个名称指向该产品的页面:
When run, the above code generates output like below:
运行后,以上代码生成如下输出:
Notice above how we were able to embed two code nuggets within the content of the foreach loop. One of them outputs the name of the Product, and the other embeds the ProductID within a hyperlink. Notice that we didn't have to explicitly wrap these code-nuggets - Razor was instead smart enough to implicitly identify where the code began and ended in both of these situations.
观察上面是如何把两段代码嵌入到foreach循环里面的。其中一段输出产品名称,另一段在超链接中嵌入产品ID。注意到我们并没有使用符号把这段代码包围起来,Razor就足以在这种情景下正确地自动识别。
How Razor Enables Implicit Code Nuggets
Razor does not define its own language. Instead, the code you write within Razor code nuggets is standard C# or VB. This allows you to re-use your existing language skills, and avoid having to learn a customized language grammar.
Razor并没有定义自己的的语言,相反,在Razor里的代码嵌入遵循C#或VB的语法。如此就允许你重用已有的语言技巧,而不需要再学习新定义的语言语法。
The Razor parser has smarts built into it so that whenever possible you do not need to explicitly mark the end of C#/VB code nuggets you write. This makes coding more fluid and productive, and enables a nice, clean, concise template syntax. Below are a few scenarios that Razor supports where you can avoid having to explicitly mark the beginning/end of a code nugget, and instead have Razor implicitly identify the code nugget scope for you:
Razor分析器已经植入智能分析功能,所以无论何时你编写C#/VB的代码嵌入都不需要明确地标记结尾。这使编码更加流畅和富有成效,并且使模板语法优雅、干净和精致。以下是一些脚本的例子,这些例子意在说明Razor能让你不用明确指定代码嵌入块的起始与结束,相应地,Razor可以在后台为你确定代码嵌入块的范围。
Property Access
属性访问
Razor allows you to output a variable value, or a sub-property on a variable that is referenced via "dot" notation:
Razor允许你输出一个变量的值,或者通过点号(".")访问变量的子属性:
You can also use "dot" notation to access sub-properties multiple levels deep:
你也可以使用点号(".")访问变量的多级子属性:
Array/Collection Indexing:
数组/集合索引:
Razor allows you to index into collections or arrays:
Razor允许你使用索引访问集合或数组:
Calling Methods:
调用方法:
Razor also allows you to invoke methods:
Razor也允许你直接调用方法:
Notice how for all of the scenarios above how we did not have to explicitly end the code nugget. Razor was able to implicitly identify the end of the code block for us.
请留意以上的所有脚本中我们为什么都不需要明确指定代码嵌入块的结尾。Razor自动为我们自动确定代码块的结尾。
Razor's Parsing Algorithm for Code Nuggets
The below algorithm captures the core parsing logic we use to support "@" expressions within Razor, and to enable the implicit code nugget scenarios above:
- Parse an identifier - As soon as we see a character that isn't valid in a C# or VB identifier, we stop and move to step 2
- Check for brackets - If we see "(" or "[", go to step 2.1., otherwise, go to step 3
- Parse until the matching ")" or "]" (we track nested "()" and "[]" pairs and ignore "()[]" we see in strings or comments)
- Go back to step 2
- Check for a "." - If we see one, go to step 3.1, otherwise, DO NOT ACCEPT THE "." as code, and go to step 4
- If the character AFTER the "." is a valid identifier, accept the "." and go back to step 1, otherwise, go to step 4
- Done!
以下算法说明了我们在Razor中使用"@"表达式的核心解析逻辑,它使得以上的隐式代码嵌入脚本成为可能:
1. 解析出一个标识符-一旦遇到一个C#或VB中的合法标识符,立即转入第2步
2. 检查括号-如果遇到"("或"[",转到2.1,否则转到第3步
2.1 不断解析直到遇到匹配的")"或"]"(支持嵌套的"()"或"[]",而忽略字符串或注释里的"()[]")
2.2 回到第2步
3. 查找"."-如果遇到一个,转到第3步,否则,拒绝接受这个"."作为代码,并转到第4步
3.1 如果"."后的是非法标识符,接受"."并转回第1步,否则转到第4步
4. 完成!
Differentiating between code and content
代码和内容的差别
Step 3.1 is a particularly interesting part of the above algorithm, and enables Razor to differentiate between scenarios where an identifier is being used as part of the code statement, and when it should instead be treated as static content:
步骤3.1是以上算法中一个特别有趣的部分,它使得Razor可以分辨脚本中作为代码声明一部分的标识符和作为静态内容的标识符:
Notice how in the snippet above we have ? and ! characters at the end of our code nuggets. These are both legal C# identifiers - but Razor is able to implicitly identify that they should be treated as static string content as opposed to being part of the code expression because there is whitespace after them. This is pretty cool and saves us keystrokes.
看看这上面的这个片段有些什么?是的,在代码嵌入的尾部的标识符!两处("?"和"!")均是合法的C#标识符-担是Razor可以自动地识别它们为静态字符内容而非把它们作为代码表达式,是因为这两个字符之后的空格。这是一个相当酷的东西,让我们免去了多敲多少次键盘啊。
Explicit Code Nuggets in Razor
Razor is smart enough to implicitly identify a lot of code nugget scenarios. But there are still times when you want/need to be more explicit in how you scope the code nugget expression. The @(expression) syntax allows you to do this:
Razor足够智能,它会自动识别大量的代码嵌入脚本。但有时仍需明确指定你所要的代码嵌入范围。语法"@(表达式)"就是应对这个要求的:
You can write any C#/VB code statement you want within the @() syntax. Razor will treat the wrapping () characters as the explicit scope of the code nugget statement. Below are a few scenarios where we could use the explicit code nugget feature:
使用"@()"你可以编写任何C#/VB代码声明来实现你想要的。Razor将把包在()的代码当作显式代码嵌入声明的范围所在。下面是一些脚本,用来说明显式代码嵌入的特性:
Perform Arithmetic Calculation/Modification:
执行算术计算/修改:
You can perform arithmetic calculations within an explicit code nugget:
可以在显式代码嵌入中执行算术计算:
Appending Text to a Code Expression Result:
在代码表达式结果后追加文本:
You can use the explicit expression syntax to append static text at the end of a code nugget without having to worry about it being incorrectly parsed as code:
可以使用显式表达式语法在代码嵌入结尾追加静态文本,且无须担心会被错误解析成代码:
Above we have embedded a code nugget within an <img> element's src attribute. It allows us to link to images with URLs like "/Images/Beverages.jpg". Without the explicit parenthesis, Razor would have looked for a ".jpg" property on the CategoryName (and raised an error). By being explicit we can clearly denote where the code ends and the text begins.
上面的例子在<img>元素的src属性中增加了一个代码嵌入。这样一来,使得图片可以链接到诸如"/Images/Beverages.jpg"的URL。倘若没有这对圆括号,Razor将会寻找一个CategoryName下的子属性".jpg"(显然这将引发错误)。使用显式代码嵌入,可以清楚地指示代码的起始和结束。
Using Generics and Lambdas
使用泛型和拉姆达表达式
Explicit expressions also allow us to use generic types and generic methods within code expressions - and enable us to avoid the <> characters in generics from being ambiguous with tag elements.
显示表达式支持使用泛型和类方法-并能有效避免泛型中"<>"和标签中的"<>"所引起的的混淆。
One More Thing….Intellisense within Attributes
We have used code nuggets within HTML attributes in several of the examples above. One nice feature supported by the Razor code editor within Visual Studio is the ability to still get VB/C# intellisense when doing this.
以上已经展示了在HTML属性中使用代码嵌入的众多例子。Razor代码编辑器的另一个好用特性就是仍然保留VS对VB/C#的智能感知功能。
Below is an example of C# code intellisense when using an implicit code nugget within an <a> href="" attribute:
下面是通过<a>标签的"href"属性说明隐式代码嵌入里使用C#代码智能感知的例子:
Below is an example of C# code intellisense when using an explicit code nugget embedded in the middle of a <img> src="" attribute:
下面是通过<img>标签的"src"属性说明显式代码嵌入里使用C#代码智能感知的例子:
Notice how we are getting full code intellisense for both scenarios - despite the fact that the code expression is embedded within an HTML attribute (something the existing .aspx code editor doesn't support). This makes writing code even easier, and ensures that you can take advantage of intellisense everywhere.
尽管代码表达式是嵌入到HTML属性的,但我们仍需要注意到为什么Razor代码编辑器能同时在两种脚本(显式和隐式代码嵌入)中拥有智能感知功能(而已存的.aspx代码编辑器却不具备)。这样一来,写代码更加简单,而且保证你随处充分发挥智能感知的优点。
Summary
Razor enables a clean and concise templating syntax that enables a very fluid coding workflow. Razor's ability to implicitly scope code nuggets reduces the amount of typing you need to perform, and leaves you with really clean code.
Razor允许使用干净简洁的模板语法,使编程流畅无阻。Razor能够自动识别隐式代码嵌入,大大减少了想要执行的代码键入,留给你一个真正干净的代码。
When necessary, you can also explicitly scope code expressions using a @(expression) syntax to provide greater clarity around your intent, as well as to disambiguate code statements from static markup.
有必要的话,使用显式范围代码表达式("@(表达式)")语法更明确地指明你所想要范围,也可以消除代码声明时静态标记。
Hope this helps,
Scott
P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu
希望以上对你有所帮助
斯科特
附:除此博客之外,我也使用推特来快速更新信息和分享链接。我的推特:twitter.com/scottgu
请发表评论