ASP.NET Core MVC 視圖

ASP.NET Core MVC中視圖的知識和ASP.NET MVC有不少類似之處,學習難度較低。如下內容主要體現了編程中模塊化的思想,模塊化才應是咱們關注的重點。css

Layout

佈局用於提供各個頁面所需的公共部分,如:菜單、頁頭、頁尾等。在ASP.NET Core中默認的佈局文件是位於/Views/Shared文件夾下的_Layout.cshtml文件:html

咱們一般在_Layout.cshtml中引入公共資源,如:前端

<link href="~/css/reset.css" rel="stylesheet" />
<link href="~/css/index.css" rel="stylesheet" /><script src="~/js/common/net/ajaxHandler.js"></script>
<environment names="Development">
    <script src="~/js/lib/vue/vue.js"></script>
</environment>
<environment names="Production">
    <script src="~/js/lib/vue/vue.min.js"></script>
</environment>

 

指定佈局文件

能夠在Razor視圖(即,cshtml文件)中使用Layout屬性來指定使用哪一個佈局文件:vue

@{
    Layout="_Layout";
}

ASP.NET Core MVC搜索佈局文件的方式與局部視圖同樣,下文中會詳細說明。默認狀況下,在佈局文件中必須調用RenderBody方法。還可使用RenderSection方法來引入section程序員

View Import & View Start

View Import

能夠在_ViewImport.cshtm文件中添加命名空間或者Tag Helper以供其它視圖中使用,如:ajax

@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

_ViewImport.cshtm文件可使用如下指令:編程

  • @addTagHelperapi

  • @removeTagHelper服務器

  • @tagHelperPrefixmvc

  • @using

  • @model

  • @inherits

  • @inject

_ViewImport.cshtm文件不支持Razor文件的其它特性,如:function、section等。對於多個_ViewImports.cshtml的狀況,指令運行結果遵循以下規則:

  • @addTagHelper, @removeTagHelper: 按照前後順序執行

  • @tagHelperPrefix: 後執行的結果覆蓋先執行的結果

  • @model: 後執行的結果覆蓋先執行的結果

  • @inherits: 後執行的結果覆蓋先執行的結果

  • @using: 引入所指定的全部命名空間,但忽略重複引用

  • @inject: 後注入覆蓋先注入的同名屬性

View Start

_ViewStart.cshtml文件中的代碼會在全部完整視圖(full view,not layout,not partial view)文件被渲染以前執行。

 

默認狀況下,ViewImports.cshtmlViewStart.cshtml文件直接位於Views文件夾下:

  • 相比其它位置的其它位置ViewImports.cshtmlViewStart.cshtml,直接位於Views文件夾中的ViewImports.cshtmlViewStart.cshtml文件會優先執行

  • 後執行的ViewImports.cshtml文件中的內容有可能會覆蓋先執行ViewImports.cshtml文件中的內容

  • ViewImports.cshtmlViewStart.cshtml文件的做用域是當前目錄及子目錄

Tag Helper

Tag Helper可讓服務器端代碼參與到在Razor文件中建立和渲染HTML元素的工做中。

自定義Tag Helper:

public class XfhTagHelper : TagHelper
{
    public string Content { set; get; }
​
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";
        output.Attributes.Add("href", "https://www.google.com");
        output.Content.SetContent(Content);
    }
}

使用Tag Helper:

@addTagHelper *,Web
​
<xfh content="haha">customer tag helper</xfh>

Tag Helper與HTML Helper有些類似,兩者不一樣之處可參考:Tag Helpers compared to HTML Helpers

Tag Helper具備如下優勢:

  • 類HTML語法

    這一點是我喜歡Tag Helper的緣由,使用Tag Helper可使cshtml文件中後臺代碼與前端的搭配更和諧,利於提高代碼可讀性

  • 語法智能感知

Tag Helper 做用域

  • @addTagHelper

    @addTagHelper的第一個參數表示要加載哪些Tag Helper,使用"*"表示加載全部的Tag Helper;第二個參數表示從哪一個程序集中加載Tag Helper。示例以下:

    @* 需指明TagHelper的徹底限定名 *@
    @addTagHelper Web.TagHelpers.XfhTagHelper,Web
  • @removeTagHelper

    @removeTagHelper也有兩個參數,含義同@addTagHelper

  • @tagHelperPrefix

    給Tag Helper加上前綴標識,示例以下:

    @addTagHelper *,Web
    @tagHelperPrefix th:
    ​
    @* 不會被看成Tag Helper處理 *@
    <xfh content="haha">customer tag helper</xfh>
    <th:xfh content="tagHelperPrefix"></th:xfh>

Partial View

Partial view,局部視圖是一個Razor文件,它一般嵌套在另外一個Razor文件中。局部視圖主要用於拆分大的Razor文件及代碼複用。但請注意:

  • 局部視圖不該用來維護公共佈局中的內容,考慮使用_Layout.cshtml來維護公共佈局

    Partial views shouldn't be used to maintain common layout elements.

  • 儘可能不要在局部視圖中使用複雜的渲染邏輯,或者須要執行一些代碼片斷才能獲取到視圖元素。這種狀況考慮使用view component來替代局部視圖。

    Don't use a partial view where complex rendering logic or code execution is required to render the markup.If you need to execute code, use a view component instead of a partial view.

聲明局部視圖

局部視圖名一般如下劃線_開頭,下劃線主要用於易於辨識局部視圖文件。注意一點,在渲染局部視圖時,不會執行_ViewStart.cshtml文件中的代碼。其他與普通視圖同樣。

⚠️局部視圖中定義的section只對當前局部視圖可見

使用局部視圖

引用局部視圖文件而不帶擴展名cshtml時,在MVC框架中,會從如下路徑中加載局部視圖文件,優先級從上而下依次下降:

  1. /Areas/<Area-Name>/Views/<Controller-Name>

  2. /Areas/<Area-Name>/Views/Shared

  3. /Views/Shared

  4. /Pages/Shared

當引用局部文件帶上擴展名時,局部視圖文件必須和引用方位於相同目錄下。

 

可以使用如下方式引入局部視圖:

  <partial name="partial.cshtml" model="Model"/>
  @* 局部視圖文件後綴能夠省略,如: *@
  <partial name="partial" />
  @* 也可使用局部視圖文件全名,如: *@
  <partial name="~/Views/Shared/_PartialName.cshtml" />
  • HTML Helper

    @await Html.PartialAsync("_PartialName")

也可使用 RenderPartialAsync方法來渲染局部視圖,該方法直接將渲染結果寫入到response中,而不是返回 IHtmlContent,因此只能在Razor代碼塊中調用該方法:

@{
    await Html.RenderPartialAsync("_PartialName");
}

相比於PartialAsyncRenderParatialAsync有着更好的性能。

View Component

View component,視圖組件和局部視圖相似,但它更強大。一個視圖組件包含兩部分:ViewComponent類和一個視圖。

視圖組件不使用模型綁定,視圖組件中所用的數據有調用者提供。視圖組件有如下特色:

  • 渲染數據塊而非整個響應

  • 關注點分離、易於測試

  • 能夠有參數和業務邏輯

    MVC自己就提倡關注點分離,因此,視圖組件中應儘量只包含與渲染視圖相關的邏輯

  • 一般在層中調用

自定義視圖組件

建立視圖組件類:

  • 視圖組件繼承自ViewComponent或使用ViewComponentAttribute特性

  • 自定義類約定以ViewComponent結尾(非強制)

public class FirstViewComponent : ViewComponent
{
    // 方法名InvokeAsync是基於約定的,同步方法名爲Invoke
    public async Task<IViewComponentResult> InvokeAsync(string descript)
    {
        return View<string>(descript);
    }
}

⚠️ 視圖組件類中可使用依賴注入。需注意:視圖組件不會參與到Controller的生命週期中,因此filter對它無效。

建立視圖文件:

視圖組件默認視圖名爲:Default,簡單定義視圖內容以下:

<label>
    @Model
</label>

在運行時按照如下順序搜索視圖文件:

  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}

  • /Views/Shared/Components/{View Component Name}/{View Name}

  • /Pages/Shared/Components/{View Component Name}/{View Name}

🆗 推薦使用Default做爲視圖組件的視圖文件名,且視圖文件存放路徑爲:Views/Shared/Components/{View Component Name}/{View Name}

可使用以下兩種方式來調用視圖組件:

  • Component.InvokeAsync

  • Tag Helper

@addTagHelper *,Web
​
<div class="text-center">
    @await Component.InvokeAsync("First", new { descript = "invoking view component" })
    <br />
    @* Tag Helper方式調用ViewComponent,需以vc:做爲前綴 *@
    <vc:first descript="tag helper">
    </vc:first>
</div>

⚠️ 注意,使用Tag Helper形式調用視圖組件時,組件名和組件的方法參數使用 kebab case方式,即,組件PriorityList有參數maxPriority,則調用方式以下:

<vc:priority-list max-priority="2">
</vc:priority-list>

除此以外,還能夠在Controller中調用視圖組件:

public IActionResult InvokeVC()
{
    // 注意,視圖組件名稱大小寫敏感
    return ViewComponent("First", new { Descript = "controller"});
}

View component methods

抄錄一段微軟官網上對於View component methods的總結,人太懶,就不翻譯了😂,留意加粗部分:

A view component defines its logic in an InvokeAsync method that returns a Task<IViewComponentResult> or in a synchronous Invoke method that returns an IViewComponentResult. Parameters come directly from invocation of the view component, not from model binding. A view component never directly handles a request. Typically, a view component initializes a model and passes it to a view by calling the View method. In summary, view component methods:

  • Define an InvokeAsync method that returns a Task<IViewComponentResult> or a synchronous Invokemethod that returns an IViewComponentResult.

  • Typically initializes a model and passes it to a view by calling the ViewComponent View method.

  • Parameters come from the calling method, not HTTP. There's no model binding.

  • Are not reachable directly as an HTTP endpoint. They're invoked from your code (usually in a view). A view component never handles a request.

  • Are overloaded on the signature rather than any details from the current HTTP request.

小結

本文主要對ASP.NET Core中的視圖部分作了簡要概述,相比於文中的各類概念,咱們應該把注意力放到模塊化設計上。模塊化、抽象思惟是程序員應該掌握的兩種能力。他們可讓咱們寫出高內聚、低耦合的代碼。

點擊下載Demo源碼

推薦閱讀

Tag Helpers in ASP.NET Core

View components in ASP.NET Core

Areas in ASP.NET Core

相關文章
相關標籤/搜索