ASP.NET Core MVC中視圖的知識和ASP.NET MVC有不少類似之處,學習難度較低。如下內容主要體現了編程中模塊化的思想,模塊化才應是咱們關注的重點。css
佈局用於提供各個頁面所需的公共部分,如:菜單、頁頭、頁尾等。在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
。程序員
能夠在_ViewImport.cshtm
文件中添加命名空間或者Tag Helper以供其它視圖中使用,如:ajax
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
在_ViewImport.cshtm
文件可使用如下指令:編程
@addTagHelper
api
@removeTagHelper
服務器
@tagHelperPrefix
mvc
@using
@model
@inherits
@inject
_ViewImport.cshtm
文件不支持Razor文件的其它特性,如:function、section等。對於多個_ViewImports.cshtml
的狀況,指令運行結果遵循以下規則:
@addTagHelper
, @removeTagHelper
: 按照前後順序執行
@tagHelperPrefix
: 後執行的結果覆蓋先執行的結果
@model
: 後執行的結果覆蓋先執行的結果
@inherits
: 後執行的結果覆蓋先執行的結果
@using
: 引入所指定的全部命名空間,但忽略重複引用
@inject
: 後注入覆蓋先注入的同名屬性
_ViewStart.cshtml
文件中的代碼會在全部完整視圖(full view,not layout,not partial view)文件被渲染以前執行。
默認狀況下,ViewImports.cshtml
和ViewStart.cshtml
文件直接位於Views文件夾下:
相比其它位置的其它位置ViewImports.cshtml
和ViewStart.cshtml
,直接位於Views文件夾中的ViewImports.cshtml
和ViewStart.cshtml
文件會優先執行
後執行的ViewImports.cshtml
文件中的內容有可能會覆蓋先執行ViewImports.cshtml
文件中的內容
ViewImports.cshtml
和ViewStart.cshtml
文件的做用域是當前目錄及子目錄
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文件中後臺代碼與前端的搭配更和諧,利於提高代碼可讀性
語法智能感知
@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,局部視圖是一個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框架中,會從如下路徑中加載局部視圖文件,優先級從上而下依次下降:
/Areas/<Area-Name>/Views/<Controller-Name>
/Areas/<Area-Name>/Views/Shared
/Views/Shared
/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"); }
相比於PartialAsync
,RenderParatialAsync
有着更好的性能。
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的總結,人太懶,就不翻譯了😂,留意加粗部分:
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 Invoke
method 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中的視圖部分作了簡要概述,相比於文中的各類概念,咱們應該把注意力放到模塊化設計上。模塊化、抽象思惟是程序員應該掌握的兩種能力。他們可讓咱們寫出高內聚、低耦合的代碼。
View components in ASP.NET Core