檢視 ASP.NET Core 中的元件
檢視元件
檢視元件與部分檢視類似,但功能更強大。 檢視元件不會使用模型系結,它們取決於呼叫檢視元件時所傳遞的資料。 本文是使用控制器和檢視撰寫,但檢視元件可搭配Pages 使用 Razor。
檢視元件:
- 轉譯區塊,而不是整個回應。
- 包含控制器與檢視之間的相同關注點分離和可測試性優點。
- 可以有參數和商務邏輯。
- 它通常是從配置頁面叫用。
檢視元件適用于任何可重複使用的轉譯邏輯,對於部分檢視而言太複雜,例如:
- 動態導覽功能表
- 標記雲端,它會在其中查詢資料庫
- 登入面板
- 購物車
- 最近發行的文章
- 部落格上的提要欄內容
- 會在每個頁面上呈現的登入面板,並根據使用者的登入狀態顯示登出或登入的連結
檢視元件包含兩個部分:
- 類別,通常衍生自 ViewComponent
- 其傳回的結果通常是檢視。
就像控制器一樣,檢視元件可以是 POCO,但大部分開發人員都可以利用衍生自 ViewComponent 的方法和屬性。
考慮檢視元件是否符合應用程式的規格時,請考慮改用 Razor 元件。 Razor 元件也會結合標記與 C# 程式碼,以產生可重複使用的 UI 單位。 Razor 元件是針對提供用戶端 UI 邏輯和組合時的開發人員生產力所設計。 如需詳細資訊,請參閱ASP.NET Core Razor 元件。 如需如何將元件並 Razor 入 MVC 或 Razor Pages 應用程式的資訊,請參閱預先呈現並整合 ASP.NET Core Razor 元件。
建立檢視元件
本節包含建立檢視元件的高階需求。 在本文稍後,我們會詳細檢查每個步驟,並建立檢視元件。
檢視元件類別
您可以透過下列任一項來建立檢視元件類別:
- 源于 ViewComponent
- 以
[ViewComponent]
屬性裝飾類別,或衍生自具有[ViewComponent]
屬性的類別 - 建立名稱結尾為尾碼的類別
ViewComponent
與控制器類似,檢視元件必須是公用、非巢狀和非抽象類別。 檢視元件名稱是已移除尾碼的 ViewComponent
類別名稱。 它也可以使用 Name 屬性明確地指定。
檢視元件類別:
若要防止具有不區分大小寫 ViewComponent
尾碼的類別被視為檢視元件,請使用 屬性裝飾類別 [NonViewComponent]
:
using Microsoft.AspNetCore.Mvc;
[NonViewComponent]
public class ReviewComponent
{
public string Status(string name) => JobStatus.GetCurrentStatus(name);
}
檢視元件方法
檢視元件會在下列專案中定義其邏輯:
InvokeAsync
傳回Task<IViewComponentResult>
的方法。Invoke
傳回 的 IViewComponentResult 同步方法。
參數直接來自檢視元件的引動過程,而不是來自模型繫結。 檢視元件絕不會直接處理要求。 通常,檢視元件會初始化模型,並呼叫 View
方法將其傳遞至檢視。 簡要來說,檢視元件方法:
- 定義傳回
Task<IViewComponentResult>
的InvokeAsync
方法或傳回IViewComponentResult
的同步Invoke
方法。 - 通常會藉由呼叫 ViewComponent.View 方法,初始化模型並將其傳遞至檢視。
- 參數來自呼叫端方法,而非 HTTP。 沒有模型繫結。
- 無法直接以 HTTP 端點的形式連線。 它們通常會在檢視中叫用。 檢視元件絕不會處理要求。
- 已多載在簽章上,而非目前 HTTP 要求中的任何詳細資料。
檢視搜尋路徑
執行階段會搜尋下列路徑中的檢視:
- /Views/{控制器名稱}/Components/{檢視元件名稱}/{檢視名稱}
- /Views/Shared/Components/{檢視元件名稱}/{檢視名稱}
- /Pages/Shared/Components/{檢視元件名稱}/{檢視名稱}
搜尋路徑適用于使用控制器 + 檢視和 Razor 頁面的專案。
檢視元件的預設檢視名稱為 Default
,這表示檢視檔案通常會命名為 Default.cshtml
。 建立檢視元件結果或呼叫 View
方法時,可以指定不同的檢視名稱。
建議您命名檢視檔案 Default.cshtml
,並使用 Views/Shared/Components/{View Component Name}/{View Name} 路徑。 PriorityList
此範例 Views/Shared/Components/PriorityList/Default.cshtml
中使用的檢視元件會用於檢視元件檢視。
自訂檢視搜尋路徑
若要自訂檢視搜尋路徑,請修改 Razor 的 ViewLocationFormats 集合。 例如,若要搜尋路徑 /Components/{View Component Name}/{View Name}
內的檢視,請將新專案新增至集合:
using Microsoft.EntityFrameworkCore;
using ViewComponentSample.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews()
.AddRazorOptions(options =>
{
options.ViewLocationFormats.Add("/{0}.cshtml");
});
builder.Services.AddDbContext<ToDoContext>(options =>
options.UseInMemoryDatabase("db"));
var app = builder.Build();
// Remaining code removed for brevity.
在上述程式碼中,預留位置 {0}
代表路徑 Components/{View Component Name}/{View Name}
。
叫用檢視元件
若要使用檢視元件,請在檢視內呼叫下列項目:
@await Component.InvokeAsync("Name of view component",
{Anonymous Type Containing Parameters})
參數會傳遞至 InvokeAsync
方法。 發行 PriorityList
項中開發的檢視元件是從檢視檔案叫用。 Views/ToDo/Index.cshtml
在下列程式碼中,會 InvokeAsync
使用兩個參數呼叫 方法:
</table>
<div>
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
將檢視元件叫用為標籤協助程式
檢視元件可以叫用為 標籤協助程式:
<div>
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@{
int maxPriority = Convert.ToInt32(ViewData["maxPriority"]);
bool isDone = Convert.ToBoolean(ViewData["isDone"]);
}
<vc:priority-list max-priority=maxPriority is-done=isDone>
</vc:priority-list>
</div>
標籤協助程式依照 Pascal 命名法大小寫慣例的類別和方法參數會轉譯成其 Kebab 字體。 用來叫用檢視元件的標籤協助程式會使用 <vc></vc>
項目。 檢視元件指定如下:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
若要使用檢視元件作為標籤協助程式,請使用 @addTagHelper
指示詞註冊包含檢視元件的組件。 如果檢視元件位於名為 MyWebApp
的元件中,請將下列指示詞新增至 _ViewImports.cshtml
檔案:
@addTagHelper *, MyWebApp
檢視元件可以註冊為標籤協助程式,以參考檢視元件的任何檔案。 如需如何註冊標籤協助程式的詳細資訊,請參閱管理標籤協助程式範圍。
本教學課程中使用的 InvokeAsync
方法:
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
在上述標記中,檢 PriorityList
視元件會 priority-list
變成 。 檢視元件的參數會以 Kebab 字體傳遞為屬性。
直接從控制器叫用檢視元件
檢視元件通常會從檢視叫用,但可以直接從控制器方法叫用它們。 雖然檢視元件未定義控制器之類的端點,但可以實作傳回 內容的 ViewComponentResult
控制器動作。
在下列範例中,檢視元件會直接從控制器呼叫:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
建立基本檢視元件
下載、建置和測試起始程式碼。 它是具有 ToDo
控制器的基本專案,可顯示 ToDo 專案清單。
更新控制器以傳入優先順序和完成狀態
Index
更新 方法以使用優先順序和完成狀態參數:
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.Controllers;
public class ToDoController : Controller
{
private readonly ToDoContext _ToDoContext;
public ToDoController(ToDoContext context)
{
_ToDoContext = context;
_ToDoContext.Database.EnsureCreated();
}
public IActionResult Index(int maxPriority = 2, bool isDone = false)
{
var model = _ToDoContext!.ToDo!.ToList();
ViewData["maxPriority"] = maxPriority;
ViewData["isDone"] = isDone;
return View(model);
}
新增 ViewComponent 類別
將 ViewComponent 類別新增至 ViewComponents/PriorityListViewComponent.cs
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents;
public class PriorityListViewComponent : ViewComponent
{
private readonly ToDoContext db;
public PriorityListViewComponent(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();
}
}
程式碼的注意事項:
檢視元件類別可以包含在專案的任何資料夾中。
由於類別名稱 PriorityListViewComponent 以後綴 ViewComponent結尾,因此執行時間會在從檢視參考類別元件時使用字串
PriorityList
。[ViewComponent]
屬性可以變更用來參考檢視元件的名稱。 例如,類別可能已使用下列[ViewComponent]
屬性命名XYZ
:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponent
[ViewComponent]
上述程式碼中的 屬性會指示檢視元件選取器使用:- 尋找與元件相關聯的檢視時的名稱
PriorityList
- 從檢視參考類別元件時,字串 「PriorityList」。
- 尋找與元件相關聯的檢視時的名稱
元件會使用相依性插入,讓資料內容可供使用。
InvokeAsync
會公開可從檢視呼叫的方法,而且可能需要任意數目的引數。InvokeAsync
方法會傳回一組符合isDone
和maxPriority
參數的ToDo
項目。
建立檢視元件 Razor 檢視
建立 Views/Shared/Components 資料夾。 此資料夾必須命名為 Components。
建立 Views/Shared/Components/PriorityList 資料夾。 此資料夾名稱必須符合檢視元件類別的名稱,或類別的名稱減去尾碼。 如果使用 屬性
ViewComponent
,類別名稱必須符合屬性指定。建立檢
Views/Shared/Components/PriorityList/Default.cshtml
Razor 視:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>
檢 Razor 視會取得 的清單
TodoItem
並加以顯示。 如果檢視元件InvokeAsync
方法未傳遞檢視的名稱, 預設 會依慣例用於檢視名稱。 若要覆寫特定控制器的預設樣式,請在控制器特定檢視資料夾中新增檢視 (例如 Views/ToDO/Components/PriorityList/Default.cshtml)。如果檢視元件是控制器特定的,則可以將它新增至控制器特定的資料夾。 例如,
Views/ToDo/Components/PriorityList/Default.cshtml
是控制器特定的。div
將包含對優先順序清單元件的呼叫新增至檔案底部Views/ToDo/index.cshtml
:</table> <div> Maxium Priority: @ViewData["maxPriority"] <br /> Is Complete: @ViewData["isDone"] @await Component.InvokeAsync("PriorityList", new { maxPriority = ViewData["maxPriority"], isDone = ViewData["isDone"] } ) </div>
@await Component.InvokeAsync
標記顯示呼叫檢視元件的語法。 第一個引數是我們想要叫用或呼叫之元件的名稱。 後續參數會傳遞至元件。 InvokeAsync
可以採用任意數目的引數。
測試應用程式。 下圖顯示 ToDo 清單和優先順序項目:
可以直接從控制器呼叫檢視元件:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
指定檢視元件名稱
在某些情況下,可能需要複雜的檢視元件,才能指定非預設檢視。 下列程式碼示範如何從 InvokeAsync
方法指定 「PV」 檢視。 更新 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 檢視。
@model IEnumerable<ViewComponentSample.Models.TodoItem>
<h2> PVC Named Priority Component View</h2>
<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>
執行應用程式,並驗證 PVC 檢視。
如果未轉譯PV 檢視,請確認呼叫優先順序為 4 或更新版本的檢視元件。
檢查檢視路徑
將優先順序參數變更為 3 或更小,以不傳回優先順序檢視。
暫時將 重新命名
Views/ToDo/Components/PriorityList/Default.cshtml
為1Default.cshtml
。測試應用程式,發生下列錯誤:
An unhandled exception occurred while processing the request. InvalidOperationException: The view 'Components/PriorityList/Default' wasn't found. The following locations were searched: /Views/ToDo/Components/PriorityList/Default.cshtml /Views/Shared/Components/PriorityList/Default.cshtml
將
Views/ToDo/Components/PriorityList/1Default.cshtml
複製到Views/Shared/Components/PriorityList/Default.cshtml
。將一些標記新增至 共用 ToDo 檢視元件檢視,以指出檢視來自 共用資料夾 。
測試 Shared 元件檢視。
避免硬式編碼字串
針對編譯時間安全,請將硬式編碼檢視元件名稱取代為類別名稱。 將 PriorityListViewComponent.cs 檔案更新為不使用 「ViewComponent」 尾碼:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
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();
}
}
檢視檔案:
</table>
<div>
Testing nameof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(nameof(PriorityList),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
採用 CLR 類型的方法多 Component.InvokeAsync
載會使用 typeof
運算子:
</table>
<div>
Testing typeof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(typeof(PriorityList),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
執行同步工作
如果不需要非同步工作,架構會處理叫用同步 Invoke
方法。 下列方法會建立同步 Invoke
檢視元件:
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents
{
public class PriorityListSync : ViewComponent
{
private readonly ToDoContext db;
public PriorityListSync(ToDoContext context)
{
db = context;
}
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var x = db!.ToDo!.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToList();
return View(x);
}
}
}
檢視元件的 Razor 檔案:
<div>
Testing nameof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(nameof(PriorityListSync),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
例如,檢視元件會在檔案 (中 Razor 叫用, Views/Home/Index.cshtml
) 使用下列其中一種方法:
若要使用 IViewComponentHelper 方法,請呼叫 Component.InvokeAsync
:
@await Component.InvokeAsync(nameof(PriorityList),
new { maxPriority = 4, isDone = true })
若要使用標籤協助程式,請使用 @addTagHelper
指示詞註冊包含檢視元件的組件 (檢視元件位於稱為 MyWebApp
的組件中):
@addTagHelper *, MyWebApp
在標記檔案中使用 Razor 檢視元件標籤協助程式:
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
的方法簽章 PriorityList.Invoke
是同步的,但在 Razor 標記檔案中尋找並呼叫 方法 Component.InvokeAsync
。
其他資源
檢視或下載範例程式碼 \(英文\) (如何下載)
檢視元件
檢視元件與部分檢視類似,但功能更強大。 檢視元件不會使用模型繫結,並且只取決於呼叫它時所提供的資料。 本文是使用控制器和檢視撰寫,但檢視元件也適用于 Razor Pages。
檢視元件:
- 轉譯區塊,而不是整個回應。
- 包含控制器與檢視之間的相同關注點分離和可測試性優點。
- 可以有參數和商務邏輯。
- 它通常是從配置頁面叫用。
如果您的可重複使用轉譯邏輯對於部分檢視而言太過複雜,則檢視元件是處理它的預定位置,例如:
- 動態導覽功能表
- 標籤雲端 (可在其中查詢資料庫)
- 登入面板
- 購物車
- 最近發行的文章
- 一般部落格上的資訊看板內容
- 登入面板,將在每個頁面上轉譯並根據使用者登入狀態來示範登出或登入連結
檢視元件包含兩個部分:類別 (通常衍生自 ViewComponent) ,而傳回的結果通常是檢視) (。 就像控制器一樣,檢視元件可以是 POCO,但大部分開發人員都可以利用衍生自 ViewComponent
的方法和屬性。
考慮檢視元件是否符合應用程式的規格時,請考慮改用 Razor 元件。 Razor 元件也會結合標記與 C# 程式碼,以產生可重複使用的 UI 單位。 Razor 元件是針對提供用戶端 UI 邏輯和組合時的開發人員生產力所設計。 如需詳細資訊,請參閱ASP.NET Core Razor 元件。 如需如何將元件並 Razor 入 MVC 或 Razor Pages 應用程式的資訊,請參閱預先呈現並整合 ASP.NET Core Razor 元件。
建立檢視元件
本節包含建立檢視元件的高階需求。 在本文稍後,我們會詳細檢查每個步驟,並建立檢視元件。
檢視元件類別
您可以透過下列任一項來建立檢視元件類別:
- 衍生自 ViewComponent
- 以
[ViewComponent]
屬性裝飾類別,或衍生自具有[ViewComponent]
屬性的類別 - 建立名稱結尾為尾碼 ViewComponent 的類別
與控制器類似,檢視元件必須是公用、非巢狀和非抽象類別。 檢視元件名稱是移除 "ViewComponent" 尾碼的類別名稱。 它也可以使用 ViewComponentAttribute.Name
屬性明確地指定。
檢視元件類別:
若要停止不區分大小寫 ViewComponent 尾碼的類別,不要被視為檢視元件,請使用 [NonViewComponent] 屬性裝飾類別:
[NonViewComponent]
public class ReviewComponent
{
// ...
檢視元件方法
檢視元件會在傳回 Task<IViewComponentResult>
的 InvokeAsync
方法或傳回 IViewComponentResult
的同步 Invoke
方法中定義其邏輯。 參數直接來自檢視元件的引動過程,而不是來自模型繫結。 檢視元件絕不會直接處理要求。 通常,檢視元件會初始化模型,並呼叫 View
方法將其傳遞至檢視。 簡要來說,檢視元件方法:
- 定義傳回
Task<IViewComponentResult>
的InvokeAsync
方法或傳回IViewComponentResult
的同步Invoke
方法。 - 通常會初始化模型,並呼叫
ViewComponent
View
方法將其傳遞至檢視。 - 參數來自呼叫端方法,而非 HTTP。 沒有模型繫結。
- 無法直接當成 HTTP 端點連接。 它們是透過您的程式碼所叫用 (通常是在檢視中)。 檢視元件絕不會處理要求。
- 已多載在簽章上,而非目前 HTTP 要求中的任何詳細資料。
檢視搜尋路徑
執行階段會搜尋下列路徑中的檢視:
- /Views/{控制器名稱}/Components/{檢視元件名稱}/{檢視名稱}
- /Views/Shared/Components/{檢視元件名稱}/{檢視名稱}
- /Pages/Shared/Components/{檢視元件名稱}/{檢視名稱}
搜尋路徑適用于使用控制器 + 檢視和 Razor 頁面的專案。
檢視元件的預設檢視名稱是 Default,這表示您的檢視檔案通常會命名為 Default.cshtml
。 建立檢視元件結果時,或呼叫 View
方法時,可以指定不同的檢視名稱。
建議您命名檢視檔案 Default.cshtml
,並使用 Views/Shared/Components/{View Component Name}/{View Name} 路徑。 PriorityList
此範例 Views/Shared/Components/PriorityList/Default.cshtml
中使用的檢視元件用於檢視元件檢視。
自訂檢視搜尋路徑
若要自訂檢視搜尋路徑,請修改 Razor 的 ViewLocationFormats 集合。 例如,若要搜尋路徑 「/Components/{View Component Name}/{View Name}」 內的檢視,請將新專案新增至集合:
services.AddMvc()
.AddRazorOptions(options =>
{
options.ViewLocationFormats.Add("/{0}.cshtml");
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
在上述程式碼中,預留位置 「 {0} 」 代表路徑 「Components/{View Component Name}/{View Name}」。
叫用檢視元件
若要使用檢視元件,請在檢視內呼叫下列項目:
@await 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 })
叫用檢視元件作為標籤協助程式
針對 ASP.NET Core 1.1 和更新版本,您可以叫用檢視元件作為標籤協助程式:
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
標籤協助程式依照 Pascal 命名法大小寫慣例的類別和方法參數會轉譯成其 Kebab 字體。 用來叫用檢視元件的標籤協助程式會使用 <vc></vc>
項目。 檢視元件指定如下:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
若要使用檢視元件作為標籤協助程式,請使用 @addTagHelper
指示詞註冊包含檢視元件的組件。 如果您的檢視元件位於名為 MyWebApp
的元件中,請將下列指示詞新增至 _ViewImports.cshtml
檔案:
@addTagHelper *, MyWebApp
您可以將檢視元件註冊為任何參考檢視元件的檔案標籤協助程式。 如需如何註冊標籤協助程式的詳細資訊,請參閱管理標籤協助程式範圍。
本教學課程中使用的 InvokeAsync
方法:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
在標籤 (tag) 協助程式標籤 (markup) 中:
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
在上述範例中,PriorityList
檢視元件會變成 priority-list
。 檢視元件的參數會以 Kebab 字體傳遞為屬性。
直接從控制器叫用檢視元件
檢視元件通常是從檢視中進行叫用,但您可以直接從控制器方法叫用它們。 雖然檢視元件不會定義控制器這類端點,但您可以輕鬆地實作控制器動作,以傳回 ViewComponentResult
的內容。
在此範例中,是直接從控制器呼叫檢視元件:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
逐步解說:建立簡單檢視元件
下載、建置和測試起始程式碼。 它是具有 ToDo
控制器的簡單專案,而此控制器顯示 ToDO 項目清單。
新增 ViewComponent 類別
建立 ViewComponents 資料夾,並新增下列 PriorityListViewComponent
類別:
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 PriorityListViewComponent : ViewComponent
{
private readonly ToDoContext db;
public PriorityListViewComponent(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();
}
}
}
程式碼的注意事項:
檢視元件類別可以包含在專案的任何資料夾中。
因為類別名稱 PriorityListViewComponent 以後綴 ViewComponent結尾,所以從檢視參考類別元件時,執行時間會使用字串
PriorityList
。[ViewComponent]
屬性可以變更用來參考檢視元件的名稱。 例如,類別可能已使用ViewComponent
屬性命名XYZ
:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponent
[ViewComponent]
上述程式碼中的 屬性會告知檢視元件選取器使用:- 尋找與元件相關聯的檢視時的名稱
PriorityList
- 從檢視參考類別元件時,字串 「PriorityList」。
- 尋找與元件相關聯的檢視時的名稱
元件會使用相依性插入,讓資料內容可供使用。
InvokeAsync
會公開可以從檢視中呼叫的方法,而且可以採用任意數目的引數。InvokeAsync
方法會傳回一組符合isDone
和maxPriority
參數的ToDo
項目。
建立檢視元件 Razor 檢視
建立 Views/Shared/Components 資料夾。 這個資料夾 必須 命名為
Components
。建立 Views/Shared/Components/PriorityList 資料夾。 此資料夾名稱必須符合檢視元件類別的名稱,或去掉尾碼的類別名稱 (如果我們遵循慣例,並在類別名稱中使用 ViewComponent 尾碼)。 如果您已使用
ViewComponent
屬性,則類別名稱需要符合屬性指定。建立檢
Views/Shared/Components/PriorityList/Default.cshtml
Razor 視:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>
檢 Razor 視會取得 的清單
TodoItem
,並加以顯示。 如果檢視元件InvokeAsync
方法未傳遞檢視名稱 (如我們的範例所示),則依照慣例會使用 Default 作為檢視名稱。 在教學課程稍後,我將示範如何傳遞檢視的名稱。 若要覆寫特定控制器的預設樣式,請在控制器特定檢視資料夾中新增檢視 (例如 Views/ToDO/Components/PriorityList/Default.cshtml)。如果檢視元件是控制器特定的,您可以將它新增至控制器特定的資料夾,
Views/ToDo/Components/PriorityList/Default.cshtml
() 。div
將包含對優先順序清單元件的呼叫新增至檔案底部Views/ToDo/index.cshtml
:</table> <div> @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false }) </div>
@await Component.InvokeAsync
標記顯示呼叫檢視元件的語法。 第一個引數是我們想要叫用或呼叫之元件的名稱。 後續參數會傳遞至元件。 InvokeAsync
可以採用任意數目的引數。
測試應用程式。 下圖顯示 ToDo 清單和優先順序項目:
您也可以直接從控制器呼叫檢視元件:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
指定檢視名稱
在某些情況下,可能需要複雜的檢視元件,才能指定非預設檢視。 下列程式碼示範如何從 InvokeAsync
方法指定 「PV」 檢視。 更新 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 檢視。
@model IEnumerable<ViewComponentSample.Models.TodoItem>
<h2> PVC Named Priority Component View</h2>
<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>
更新 Views/ToDo/Index.cshtml
:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
執行應用程式,並驗證 PVC 檢視。
如果未轉譯 PVC 檢視,請驗證您要呼叫的檢視元件優先順序為 4 或以上。
檢查檢視路徑
將優先順序參數變更為 3 或更小,以不傳回優先順序檢視。
暫時將 重新命名
Views/ToDo/Components/PriorityList/Default.cshtml
為1Default.cshtml
。測試應用程式,您會收到下列錯誤:
An unhandled exception occurred while processing the request. InvalidOperationException: The view 'Components/PriorityList/Default' wasn't found. The following locations were searched: /Views/ToDo/Components/PriorityList/Default.cshtml /Views/Shared/Components/PriorityList/Default.cshtml EnsureSuccessful
將
Views/ToDo/Components/PriorityList/1Default.cshtml
複製到Views/Shared/Components/PriorityList/Default.cshtml
。將一些標記新增至 共用 ToDo 檢視元件檢視,以指出檢視來自 共用資料夾 。
測試 Shared 元件檢視。
避免硬式編碼的字串
如果您想要編譯時間安全,則可以將寫在程式碼中的檢視元件名稱取代為類別名稱。 建立不含 "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();
}
}
}
using
將 語句新增至檢 Razor 視檔案,並使用 nameof
運算子:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>
<h2>ToDo nameof</h2>
<!-- Markup removed for brevity. -->
<div>
@*
Note:
To use the below line, you need to #define no_suffix in ViewComponents/PriorityList.cs or it won't compile.
By doing so it will cause a problem to index as there will be multiple viewcomponents
with the same name after the compiler removes the suffix "ViewComponent"
*@
@*@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })*@
</div>
您可以使用採用 CLR 類型的方法多 Component.InvokeAsync
載。 請記得在此案例中使用 typeof
運算子:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>
<h2>ToDo typeof</h2>
<!-- Markup removed for brevity. -->
<div>
@await Component.InvokeAsync(typeof(PriorityListViewComponent), new { maxPriority = 4, isDone = true })
</div>
執行同步工作
如果您不需要執行非同步工作,架構會處理叫用同步 Invoke
方法。 下列方法會建立同步 Invoke
檢視元件:
public class PriorityList : ViewComponent
{
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
return View(items);
}
}
檢視元件的 Razor 檔案會列出傳遞至 Invoke
方法的字串 (Views/Home/Components/PriorityList/Default.cshtml
) :
@model List<string>
<h3>Priority Items</h3>
<ul>
@foreach (var item in Model)
{
<li>@item</li>
}
</ul>
例如,檢視元件會在檔案 (中 Razor 叫用, Views/Home/Index.cshtml
) 使用下列其中一種方法:
若要使用 IViewComponentHelper 方法,請呼叫 Component.InvokeAsync
:
@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
若要使用標籤協助程式,請使用 @addTagHelper
指示詞註冊包含檢視元件的組件 (檢視元件位於稱為 MyWebApp
的組件中):
@addTagHelper *, MyWebApp
在標記檔案中使用 Razor 檢視元件標籤協助程式:
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
的方法簽章 PriorityList.Invoke
是同步的,但在 Razor 標記檔案中尋找並呼叫 方法 Component.InvokeAsync
。
所有檢視元件參數均為必要參數
檢視元件中的每個參數都是必要屬性。 請參閱這個 GitHub 問題。 如果省略任何參數:
InvokeAsync
方法簽章即不相符,因此系統不會執行此方法。- ViewComponent 不會轉譯任何標記。
- 系統不會擲回任何錯誤。