1. 程式人生 > >ASP.NET Core 十種方式擴充套件你的 Views

ASP.NET Core 十種方式擴充套件你的 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裡面,來讓它具有動態的內容。但是ViewBagViewData都是弱型別的,所以沒有智慧提示,用起來略不爽。

要在你的檢視中使用強型別資料物件,你需要定義一個Model來在檢視中使用。

@model ExtendViews.ViewModels.AboutModel

<!-- usage: --->
@Model.FullName

這種方式是不是很常見的? 下一種方式是一個更好的方式來佈局我們的檢視:

#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特有的。

譯者注:類似於以前的使用者控制元件

有時候你需要做一些分部檢視的事情,但是又包含一些業務邏輯在裡面。在過去,你可以使用ChildAction渲染結果到一個檢視中,但是,在 ASP.NET Core中,有一種新的方式來做這件事情,它就是ViewComponents(我已經寫了一篇關於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, 都有很多方法來擴充套件檢視,雖然擴充套件這些檢視的方式有些類似,但是每一種都有它最適合的地方,所以我們在使用這些特性來解決我們的問題的時候,我們應該多加思考,找到最合適的方式。