ViewComponent 1、View 組件介紹 在ASP.NET CORE MVC中,View組件有點類似於partial views,但是他們更強大,View組件不能使用model binding,當你調用它的時候僅僅依賴與你提供的數據一個View組件特點: .呈現一大塊而不是一個整體的響應。 ...
ViewComponent
1、View 組件介紹
在ASP.NET CORE MVC中,View組件有點類似於partial views,但是他們更強大,View組件不能使用model binding,當你調用它的時候僅僅依賴與你提供的數據
一個View組件特點:
.呈現一大塊而不是一個整體的響應。
.包含在控制器和視圖之間發現的相同的分離問題和可測試行優點。
.可以包含參數和業務邏輯。
.通常從佈局頁面調用。
你可以在任何可重覆使用的渲染邏輯的部分視圖中用視圖組件來替換。
例如:
.動態導航菜單
.標簽雲
.登陸面板
.購物車
.最近發表的文章
.側欄內容在一個典型的博客
.登陸的面板信息可以顯示在每一個頁面上,並顯示要註銷或登陸的鏈接,具體取決於用戶的登陸狀態
視圖組件有兩部分組成:類(通常派生自ViewComponent)和返回結果(通常為視圖). 像控制器
一樣,視圖組件可以是POCO,但大多數開發人員都希望利用從ViewComponent派生的方法和屬性
2、創建一個View組件
本節包含創建一個視圖組件。在本文的後面,我們將詳細檢查每個步驟並創建一個視圖組件。
2.1 、View Component類
一個View組件的類可以通過下麵方式創建:
.繼承ViewComponent
.使用[ViewComponent]attribute 修飾的類,或者繼承自一個[ViewComponent]attribute類的子類。
.創建一個以ViewComponent結尾的類。
像控制器一樣,View組件必須是公共的、非嵌套的,和非抽象類。視圖組件名稱是刪除"ViewComponent" 尾碼的類名稱。
也可以使用ViewComponentAttribute.Name屬性顯式指定它。
2.2、View Component 類
.支持構造函數註入
.不參與控制器的生命周期,這意味著你不能在視圖組件中使用過濾器
2.3、View Component方法
視圖組件在InvokeAsync方法中定義其邏輯,該方法返回IViewComponentResult.調用視圖組件直接用參數,而不是模型
綁定。視圖組件從不直接處理請求。通常,視圖組件初始化模型,並通過調用View方法將其傳遞給視圖。
總是來說,視圖組件方法如下:
.定義一個InvokeAsync 方法返回一個IViewComponentResult
.通常,通過調用ViewComponent View方法來初始化模型並將其傳給視圖。
.參數來自調用方法,而不是HTTP,沒有模型綁定
.不能直接作為HTTP端點訪問,他們是通過代碼調用(通常在視圖中)。視圖組件從不處理請求。
.在簽名上重裝,而不是來自當前HTTP請求的任何詳細信息
2.4、View 搜索路徑
運行時View通過搜索下列路徑:
.Views/<controller_name>/Components/<view_component_name>/<view_name>
.Views/Shared/Components/<view_component_name>/<view_name>
創建視圖組件結果或調用VIew方法時,可以指定不同的視圖名稱。
我們建議你為視圖文件命名為Default.cshtml,並使用Views/Shared/Components/<view_component_name>/<view_name>路徑
此示例中使用的PriorityList視圖組件使用Views/Shared/Components/PriorityList/Default.cshtml作為視圖組件視圖。
一個視圖組件預設的名稱是Default.cshtml 並且使用Views/Shared/Components/<view_component_name>/<view_name> 路徑.
在這個例子中我們使用PriorityList視圖組件Views/Shared/Components/PriorityList/Default.cshtml
2.4、調用一個視圖組件
在View視圖內通過如下調用視圖組件:
@Component.InvokeAsync("Name of view component", <anonymous type containing parameters>)
參數將傳遞給InvokeAsync方法。在文章中開發的PriorityList視圖組件是從Views/Todo/Index.cshtml視圖中調用的。
在下麵,InvokeAsync方法調用兩個參數:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
通過Tag Helper調用視圖組件:
對於asp.net core 1.1和更高版本,你可以作為tagHelper調用一個視圖組件。
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
上面代碼中,PriorityList視圖組件被轉化成priority-list.視圖組件的參被轉化成小寫短橫線屬性。
調用視圖組件的標簽助手使用<vc> </ vc>元素。 視圖組件指定如下:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
註意: 為了使用View Component作為Tag Helper,必須使用@addTagHelper指令註冊包含View Component的程式集。例如,
如果你的View Component位於名為"MyWebApp"的程式集,請將以下指令添加到_ViewImports.cshtml文件中:
@addTagHelper *, MyWebApp
本教程中使用的InvokeAsync方法:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
標簽助手標記
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
在上面的示例中,PriorityList視圖組件成為priority-list。
在Controller中直接調用一個組件
視圖組件通常從視圖調用,但您可以直接從控制器方法調用他們。雖然視圖組件不定義端點(如控制器),但你可以輕鬆
實現返回ViewComponentResult內容的控制器操作。
下麵代碼,View 組件直接通過控制器調用:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
2.5、創建一個ViewComponent
在代碼中註意如下幾點:
.View Component 類能包含到項目任何目錄下.
.因為類名PriorityListViewComponent以ViewComponent結尾,運行時使用字元串"PriorityList"
稍後將會做詳細解釋.
.[ViewComponent]能改變名字引用一個ViewComponent。例如,我們可以命名XYZ類,並應用ViewComponent attribute
[ViewComponent(Name = "PriorityList")]
public class XYZ : ViewComponent{}
.上面的[ViewComponent]特性告訴ViewComponent選擇器使用名稱為PriorityList 當視圖查找相關聯的組件時。
並從視圖引用類的組件時使用字元串"PriorityList"
.組件使用了依賴註入,確保數據上下文是可用的。
.InvokeAsync是公開的方法可以直接從視圖中調用,它可以傳入任意數量的參數。
.InvokeAsync方法返回滿足isDone和maxPriority參數的ToDo項集合
2.6、創建視圖組件 Razor View
.創建Views/Shared/Components 文件夾.這個文件夾的名字必須是Components。
.創建Views/Shared/Components/PriorityList 文件夾,這個文件夾名稱必須和ViewComponent類名稱相同,或者類名減去尾碼
如果你使用了ViewComponet屬性,則類名必須匹配該屬性.
.創建一個 Views/Shared/Components/PriorityList/Default.cshtml Razor view:
@model IEnumerable<ViewComponentSample.Models.TodoItem>
<h3>Priority Items</h3>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>
Razor View 返回一個列表並顯示他們.如果這個View Component 的InvokeAsync方法沒有傳遞一個View的名字,根據契約Default視圖名字將被使用。
在稍後我們將介紹如何傳遞一個視圖的名字, 要覆蓋特定控制器的預設樣式,請將視圖添加到特定於控制器的視圖文件夾(例如Views / Todo / Components / PriorityList / Default.cshtml)。
將包含調用優先順序列表組件的div添加到Views/Todo/index.cshtml文件的底部:
<div >
@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
</div>
@await Component.InvokeAsync 展示瞭如何調用ViewComponent語法.第一個參數是我們想要調用視圖組件的名稱。後續參數傳給組件,
InvokeAsync可以接受任意數量的參數可以接受任何數量的參數。
你也可以通過Controller直接調用。
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
指定一個View名稱
複雜的視圖組件有時候可能需要指定一些非預設視圖。下麵代碼顯示瞭如何從InvokeAsync方法中指定PVC視圖。
更新PriorityListViewComponent類中的InvokeAsync方法。
public async Task<IViewComponentResult> InvokeAsync(
int maxPriority, bool isDone)
{
string MyView = "Default";
// If asking for all completed tasks, render with the "PVC" view.
if (maxPriority > 3 && isDone == true)
{
MyView = "PVC";
}
var items = await GetItemsAsync(maxPriority, isDone);
return View(MyView, items);
}
複製Views/Shared/Components/PriorityList/Default.cshtml文件,重命名為Views/Shared/Components/PriorityList/PVC.cshtml
在PVC.cshtml中添加下麵代碼:
@{
ViewData["Title"] = "Default";
}
@model IEnumerable<ViewComponentSimple.ViewComponents.TodoItem>
<h3>To do PVC View</h3>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>
運行應用程式,並驗證PVC視圖。
檢查視圖路徑
.將priority參數更改0,以便不返回PVC視圖。
.臨時將Views/Todo/Components/PriorityList/Default.cshtml重命名為1Default.cshtml。
.運行App你會得到下麵錯誤:
.複製 Views/Todo/Components/PriorityList/1Default.cshtml 到 Views/Shared/Components/PriorityList/Default.cshtml.
.向共用視圖中添加一些標記,以指示視圖來自共用文件。
.測試共用文件中視圖組件.
如果你想確保編譯時類型安全,你可以用類名去替換硬編碼(不用字元串).創建一個View視圖不適用"ViewComponent" 尾碼
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents
{
public class PriorityList : ViewComponent
{
private readonly ToDoContext db;
public PriorityList(ToDoContext context)
{
db = context;
}
public async Task<IViewComponentResult> InvokeAsync(
int maxPriority, bool isDone)
{
var items = await GetItemsAsync(maxPriority, isDone);
return View(items);
}
private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
}
}
使用nameof操作符:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>
<h2>ToDo nameof</h2>
<!-- Markup removed for brevity. -->
}
</table>
<div>
@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
</div>
原文:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/view-components