ASP.NETCore⼗种⽅式扩展你的Views
现在,已经有很多种⽅式来扩展Razor视图了,我们循循渐进,先从最简单的开始。
如果你之前熟悉MVC5(以及之前的MVC)中的视图的话,有⼀部分你应该已经很熟悉了。在新的ASP.NET Core 中,那些你熟悉的⽅式有⼀部分仍然能⽤,只是Core版本针对视图⼜添加了⼀些东西。这篇⽂章,我们就来⼀起看看吧。
#1:数据视图(Typed Views)
这是⼀个不具有动态内容的最基本的⼀个视图,就是你定义⼀个ViewModel , 然后ViewModel具有⼀些默认值,在视图上直接呈现⽽已。定死的ViewModel,好像不是很常见,以⾄于你使⽤Visual Studio新建⼀个默认的Web应⽤程序的话,都看不到它。它就看起来像⼀
个*.cshtml结尾的HTML⽂件,但是,cshtml⽂件却是服务端可以解析的⼀种⽂件,所以你可以在⾥⾯使⽤⼀些Razor语法,⽐如HtmlHelpers,UrlHelpers等。同样,你可以使⽤ViewBag或者ViewData来从Controller的Action传输数据到View⾥⾯,来让它具有动态的内容。但是ViewBag和ViewData都是弱类型的,所以没有智能提⽰,⽤起来略不爽。
要在你的视图中使⽤强类型数据对象,你需要定义⼀个Model来在视图中使⽤。
@model ExtendViews.ViewModels.AboutModel
<!-- usage: --->
@Model.FullName
这种⽅式是不是很常见的?下⼀种⽅式是⼀个更好的⽅式来布局我们的视图:
reddit#2:布局(Layouts):
相当于ASP.NET的WebForms的母版页,不过它是定义Razor视图的基本布局的⼀种⽅式。它就是_Layout.cshtml, 位于 Views\Shared\ ⽂件夹⾥。通常情况下这个⽂件通常包含HTML的header,body和公⽤的⼀些东西。你可以多建⼏个互相进⾏组合,来完成整个站点的布局。其他页⾯引⽤布局视图页的时候,是这样⼦写的(注意不需要扩展名):
@{
Layout = "_Layout";
}
此调⽤需要在您的视图的第⼀⾏中。但你不需要在每⼀个视图中定义布局,如果你使⽤Visual Studio新建⼀个ASP.NET Core项⽬,Views ⽂件夹有⼀个_ViewStart.cshtml,在运⾏的时候它会⾃动的导⼊到每个视图中去。
在_Layout.cshtml有⼀个⽅法法叫RenderBody(),它就是⽤来渲染详细的视图页到模板布局视图中:
@RenderBody()
在此⽅法的位置,详情视图就会被渲染到这⾥。
#3: 区域(Sections)
有时候⼦视图中想在主视图中显⽰⼀部分html代码,⽐如javascript代码或者是css,这个时候就可以使⽤Sections,通常情况下在页⾯的结尾部分。
在主视图中(_Layout.cshtml)定义⼀个Javascripts Section:
@RenderSection("scripts", required: false)
有⼀个required参数来声明这个Section是否必须的。然后你就可以在⼦视图中这样使⽤:
@section scripts
{
<script>
$(function() {
// some more js code here;
});
</script>
}
如果你使⽤嵌套的布局,你可能需要嵌套这个区域。意思就是你在Section⾥⾯嵌套调⽤RenderSection():
@section scripts
{
@RenderSection("scripts", required: false)
}
#4: 分部视图( PartialViews)
你可以提取html页⾯中重⽤的部分,把它放到⼀个新的Razor视图中,这个视图没有⾃⼰的Action,这种视图就叫做分部视图。分部视图通常也在Views\Shard\⽂件夹。
分部视图同样也可以是⼀个数据视图,它可以从⽗视图中获取数据(但不是必须的):
@model IEnumerable<UserModel>
@if (Model.Any())
{
<ul>
@foreach (var user in Model)
{
<li>@user.FullName</li>
}
</ul>
}
这个分部视图需要从⽗视图中获取⽤户列表的数据
@{ await Html.RenderPartialAsync("Users", Model.Users);}
如果你的分部视图没有定义⽤户模型,你就不需要传第⼆个参数。
#5:视图组件(ViewComponents)
这个 ASP.NET Core特有的。
译者注:类似于以前的⽤户控件
有时候你需要做⼀些分部视图的事情,但是⼜包含⼀些业务逻辑在⾥⾯。在过去,你可以使⽤ChildActi
on渲染结果到⼀个视图中,但是,在ASP.NET Core中,有⼀种新的⽅式来做这件事情,它就是ViewComponents(我已经写了⼀篇关于的博⽂)。它类似于在MVC中的⼀种迷你的MVC,也就是说他们可以有⾃⼰的Controller,和单个的action以及view。ViewComponents是完全独⽴于你的当前视图的,但是可以通过你当前的视图传输数据。
想这样调⽤它,来渲染⼀个ViewComponents:
@Component.Invoke("Top10Articles");
可以看我的博客来学习怎么创建⾃⼰的ViewComponent。
#6: HTML助⼿(HtmlHelpers)
在HTMLHelper类中,你可以创建你⾃⼰的扩展⽅法来扩展Razor语法:
public static class HtmlHelperExtensions
{
public static HtmlString MyOwnHtmlHelper(this HtmlHelper helper, string message)
{
return new HtmlString($"<span>{message}<span>");
}
}
在你的视图中,创建⼀个可重⽤的部分是⾮常有⽤的,它⽐分部视图多包含了⼀些业务逻辑。⽐HTMLHelpers扩展更好的是新的TagHelpers,但是在扩展你视图的时候,HTMLHelpers仍然有它⾃⼰的⼀些适⽤的地⽅。
#7: 标签助⼿(TagHelper)
这是 ASP.NET Core ⾮常好的⼀个新特性。
⼀个扩展你视图的⼩助⼿,它看起来像⼀个原⽣的HTML标签⼀样。在ASP.NET Core MVC中你应该使⽤ TagHelpers 来替换HtmlHelpers,因为它们更加的简洁和容易使⽤。另⼀个巨⼤的好处就是依赖注⼊,在HtmlHelpers中是使⽤不了的,因为HtmlHelpers 扩展的都是静态内容。但TagHelpers是⼀个公共类,我们可以很容易的在它的构造函数中注⼊服务。
下⾯是⼀个很简单的⼩⽰例,来展⽰怎么样定义⼀个TagHelper:
[TargetElement("hi")]
public class HelloTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "p";
output.Attributes.Add("id", context.UniqueId);
output.PreContent.SetContent("Hello ");
output.PostContent.SetContent(string.Format(", time is now: {0}",
DateTime.Now.ToString("HH:mm")));
}
}
这⾥定义了⼀个叫做hi的标签,它以HTML标记来呈现,p标签的内容是当前时间。
使⽤:
<hi>John Smith</hi>
结果:
<p>Hello John Smith, time is now: 18:55</p>
ASP.NET Core MVC 已经默认提供了很多TagHelpers来替换以前的HtmlHelpers。例如ActionLink已经被新的TagHelper所替换:
@Html.ActionLink(“About me”, “About”, “Home”)
新的TagHelper像这样来创建⼀个link:
<a asp-controller=”Home” asp-action=”About”>About me</a>
以上两种⽅式来创建⼀个a标签的结果:
<a href=”/Home/About”>About me</a>
可以看到,TagHelpers看起来更像原⽣的HTML,他们在视图中更加的直观,更⾼的可读性,并且更容易使⽤。
#8: 依赖注⼊(Dependency Injection)
这也是ASP.NET Core的新特性。
在扩展你的视图的时候,可以使⽤依赖注⼊了,这是⼀个⾮常⼤改进。是的,你可以在你的视图中使⽤DI了。
在StackOverflow和reddit有⼈这样问?
这真的有意义吗? 这不是会搞乱我的视图吗?这不是与MVC模式背离吗?
我认为,不是这样的。的确,在真正需要的地⽅你才使⽤,并且,你使⽤的时候需要⾮常⼩⼼。有这样⼀个有效的场景:你创建⼀个表单来编辑⽤户的资料信息(User Profile), ⽤户可以添加他的公司位置,
地址,国家城市等等,我不愿意从Action到View中传输公司位置 ,地址和国家城市。我只愿意通过⽤户资料本⾝(User Profile), 我只想在 Action 中处理⽤户资料(User Profile)。这时候可以注⼊服务来给我查询数据,这就是为什么这种情况下它是⾮常有⽤的。它可以让我们的Action和ViewModel 保持⾮常的⼲净。
在Startup.cs中的ConfigureServices来注册你具体的服务,然后你就可以在视图中这样来使⽤,只需要⼀⾏代码:
@inject DiViews.Services.ICountryService CountryService;
现在你可以在你的视图中使⽤ContryService来填充国家下拉列表。
我在中写了很多关于依赖注⼊的博⽂。
#9: 函数(Functions)
在⼀个ASP.NET MVC 项⽬中,我从来没有真正的使⽤过函数这个功能。我只在⼀个Umbraco的CMS系统中⽤过⼀次。不管怎么说,这也是扩展你视图的另⼀种⼩技巧。也许你有很复杂视图⽅⾯的业务逻辑,在这种情况下,你可以在你的视图中写C#⽅法:
@functions
{
public string ReverseString(string input)
{
return String.Join("", input.Reverse());
}
}
#10: 配置全局视图(Global view configuration)
最后⼀点,你可以在_ViewImports.cshtml⽂件中,来配置你其他视图中使⽤的⼀些⽐较公⽤的 using 引⽤,依赖注⼊等。
总结
不管是以前的MVC还是新的Core MVC, 都有很多⽅法来扩展视图,虽然扩展这些视图的⽅式有些类似,但是每⼀种都有它最适合的地⽅,所以我们在使⽤这些特性来解决我们的问题的时候,我们应该多加思
考,到最合适的⽅式。
译者注:本⽂翻译并⾮逐字翻译,由于⽔平有限,难免出现⼀些错误和翻译不准确的地⽅,希望读者能够指出并堪正,不胜感激。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论