這一節要來說ViewComponent
其實這跟Partial View要做的事情是差不多的,也是用來做重複使用的元件
但兩者的差異在Partial View會更專注在只有處理HTML的版型部分,不太參與商業邏輯程式的部分
雖然Partial View一樣可以寫一些程式,但這邊不建議寫後端資料處理的邏輯程式,頂多寫一些Razor版面控制的程式
如果要寫到商業邏輯或資料處理的程式,我們則會使用ViewComponent來實作
例如下圖yt左邊的選單部分

我們一樣可以用Partial View把它切分出去,但很明顯的這個選單部分是有自己的邏輯程式跟撈取資料庫的處理程式
如果我們用Partial View來寫,大概可以有兩種方式
第一種,把邏輯程式跟選單資料寫在主controller跟view,處理好後再丟給Partial View顯示
但這樣會讓主controller的邏輯程式太臃腫耦合性太高,不利於後續維護
第二種,我們把邏輯程式跟選單資料的撈取都寫進Partial View裡面
雖然可以,但Partial View的架構本來就不是用來寫這類的程式,對日後維護會不太好
所以面對這種情況,我們會選擇ViewComponent
那今天就來再來改在news2index,雖然目前只有一個功能,但如果以後是好多功能組合成一個內容
我們就可能會把顯示列表的這部份給切出去成一個ViewComponent
那首先我們要建一個ViewComponents資料夾

之後的ViewComponent程式都會放在這裡,這是預設的路徑,當然也可以自訂路徑,這以後有機會再講
再來在Views/Shared下建一個Components資料夾

之後ViewComponent檢視的部分都會放這裡,這一樣是預設路徑,當然也可以自訂路徑,這以後有機會再講
接著我們就要來建立這個部分的元件了,那我們這邊叫NewsList元件
先在ViewComponents建立一個NewsListViewComponent.cs檔案
以下是同步寫法,一樣也可以用非同步,但我這邊喜歡用同步寫法
using Microsoft.AspNetCore.Mvc;
namespace Kcg.ViewComponents
{
public class NewsListViewComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
return View();
}
}
}
再來再Views/Shared/Components下建立一個對應的View

這是預設寫法,同名資料夾+Default.cshtml就是對應的View的位置
接著我們開始把原來寫在new2index的html跟程式搬過去
NewsListViewComponent.cs
namespace Kcg.ViewComponents
{
public class NewsListViewComponent : ViewComponent
{
private readonly KcgContext _context;
public NewsListViewComponent(KcgContext context)
{
_context = context;
}
public IViewComponentResult Invoke()
{
var result = from a in _context.News
join b in _context.Department on a.DepartmentId equals b.DepartmentId
join c in _context.Employee on a.UpdateEmployeeId equals c.EmployeeId
select new NewsDto
{
Click = a.Click,
Enable = a.Enable,
EndDateTime = a.EndDateTime,
NewsId = a.NewsId,
StartDateTime = a.StartDateTime,
Title = a.Title,
UpdateDateTime = a.UpdateDateTime,
UpdateEmployeeName = c.Name,
DepartmentName = b.Name,
Content = a.Contents
};
return View(result);
}
}
}
Default.cshtml
@model IEnumerable<NewsDto>
@foreach (var item in Model)
{
<div>
@await Html.PartialAsync("NewsBox", item)
</div>
}
<div style="clear:both"></div>
最後我們再在new2index中引入我們建好的NewsListViewComponent
Index.cshtml
@{
ViewData["Title"] = "Index2";
}
@await Component.InvokeAsync("NewsList");
這樣就完成了,看一下網頁有沒有正常運作

這樣就成功的將新聞列表區塊切成一個ViewComponent了
如果主頁面想要傳遞參數給ViewComponent可以這樣寫
@await Component.InvokeAsync("NewsList", "參數");
@await Component.InvokeAsync("NewsList", new { 自訂名稱 = "參數" });
對應的接收方式
//對應的類型跟隨意的變數名稱
public IViewComponentResult Invoke(string value)
{
}
//對應的類型跟指定的變數名稱
public IViewComponentResult Invoke(string 自訂名稱)
{
}
範例檔:下載