iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
1
Modern Web

打net core肉飯系列 第 16

[2020鐵人賽] Day16 - Partial View與ViewComponent

  • 分享至 

  • xImage
  •  

本章繼續延續View端的介紹,來談談Partial View與ViewComponent這兩個在View端最常使用的共用頁面吧。

Partial View
主要作用是,在不同的View中,可以重複使用的HTML,其命名通常習慣以底線(underline)來命名,大多都會放在/Views/Shared資料夾底下。

接著來新增一個看看
Shared資料夾底下->右鍵點選新增->檢視
https://ithelp.ithome.com.tw/upload/images/20201001/20111766pEAgwMUnEZ.png

_PartialView頁面,我們設計印出一串list試試看,由於是從Index導頁,所以我們要在這個Action準備好餵給PartialView的資料才行
Controller如下:

        public IActionResult Index()
        {
            List<Comment> data = new List<TestModel> {
         new TestModel { Id = 100, Subject = "A" },
         new TestModel { Id = 200, Subject = "B" },
         new TestModel { Id = 300, Subject = "C" }
       };
            return View(data);
        }
@model IEnumerable<IronMan.Models.TestModel>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>TestPartialView</title>
</head>
<body>
    <h1>TestPartialView</h1>
    @*<ul>
            @foreach (var item in Model)
            {
                <li>@item.Id, @item.Subject</li>
            }
        </ul>*@
    <!--以MVC5方法呼叫寫法-->
    @Html.Partial("_TestView")
    
    <!--也可以寫成非同步方式-->
    @await Html.PartialAsync("_TestView")
    
    <!--也可以寫成指定路徑非同步方式-->
    @await Html.PartialAsync("~/views/shared/_TestView.cshtml")
    
    <!--Tag Helper也是沒問題-->
    <partial name="_TestView" />
    
    <!--Tag Helper指定路徑也是沒問題-->
    <partial name="~/views/shared/_TestView.cshtml" />
</body>
</html>

接著,主頁要使用_PartialView
以@Html.Partial("_TestView")呼叫,注意要在頁面準備好model接收資料

@model IEnumerable<IronMan.Models.TestModel>
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>主頁</title>
</head>
<body>
    <h1>GetPartialView</h1>
    @Html.Partial("_TestView")
</body>
</html>

ViewComponent
接著來介紹ViewComponent,他主要是為了取代舊版MVC5的Html.Action,非常像PartialView,但提供了更多功能,但最大的不同為,不提供Model Binding,資料由呼叫時決定,通常會從Layout呼叫。

有幾項注意事項必須要知道

  • class
    • 通常是public
    • 可以繼承ViewComponent或是有套用ViewComponent的Attribute
    • 命名上來說,通常要命xxxViewComponent以好辨識
    • 支援相依性注入
    • 不依附Controller的生命週期(資料準備不用要伴隨Controller一起)
  • return
    • 通常回傳View

綜合以上,我其實比較喜歡ViewComponent這個設定-不依附Controller的生命週期(資料準備不用要伴隨Controller一起),因為以前在使用PartialView時,我必須在呼叫的Controller準備好PartialView要用的資料,整個Controller就會顯得超肥,而且十分不好維護,但若使用ViewComponent,我們的耦合度就鬆散,可以自行管控,所以十分推薦使用ViewComponent,要使用 ViewComponent,必須在.cshtml最上方加入@addTagHelper *,這個其實在我們之前的ViewImport有加入過了。

預設搜尋路徑:
Views/xxxController/Components/xxxViewComponent/View名稱.cshtml
Views/Shared/Components/xxxViewComponent/View名稱.cshtml

呼叫方式:

@await Component.InvokeAsync("View名稱")

<!--vc代表ViewComponent-->
<vc:ViewComponent名稱></vc:ViewComponent名稱>

接著,將上面PartialView的範例,改成ViewComponent看看吧。
Controller如下:

        public IActionResult Index()
        {  
            return View();
        }

新增ViewComponent類別:
https://ithelp.ithome.com.tw/upload/images/20201001/20111766wGQ9gmepJj.png

using Microsoft.AspNetCore.Mvc;
using IronMan.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IronMan.ViewComponents
{
    public class TestViewComponent : ViewComponent
    {
        public async Task<IViewComponentResult> InvokeAsync()
        {
            List<TestModel> data = new List<TestModel> {
              new TestModel{Id=100,Subject="A"},
              new TestModel{Id=200,Subject="B"},
              new TestModel{Id=300,Subject="C"}
            };

            return View(data);
        }
    }
}

主頁面呼叫ViewComponent:


@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <h1>Test</h1>
    @await Component.InvokeAsync("TestViewComponent")
    <vc:test></vc:test>
</body>
</html>

是不是輕便許多,不用再把Controller寫的肥大。

參考資料
https://docs.microsoft.com/zh-tw/aspnet/core/mvc/views/view-components?view=aspnetcore-3.1


上一篇
[2020鐵人賽] Day15 - HTML Helper與Tag Helper
下一篇
[2020鐵人賽] Day17 - 使用Layout
系列文
打net core肉飯30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言