iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
0
Modern Web

今晚,我想來點Blazor系列 第 17

Day 17:樣板元件(1)

  • 分享至 

  • xImage
  •  

前幾篇我們學到Parameter的用法,知道可以將資料透過Parameter傳給其他元件,但如果想要傳的是一個<a>標籤,一個<img>,或是多個不同的內容該怎麼做呢? 可以試試看用樣板元件。

今天要做的例子是這個:
https://ithelp.ithome.com.tw/upload/images/20201001/20130058Tp0IhZDeyI.jpg
這邊用boostrap的card來當作我們的樣板,我們現在要做的,就是將圖片、品名和價錢傳進這個card元件裡面。

建立ProductCard元件:

<div class="card">
    @ChildContent
    <div class="card-body">
        <h5 class="card-title">@ProductName</h5>
        <p class="card-text"><span class="text-muted">Price:$@Price</span></p>
    </div>
</div>

@code {
    [Parameter]
    public string ProductName { get; set; }

    [Parameter]
    public decimal Price { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }
}
  • 品名和價錢這邊都先用一般Parameter傳入,唯獨圖片有可能會更換,所以讓呼叫端決定。
  • 要讓呼叫端傳<img>過來的話,要新增一個RenderFragment Parameter,名稱須為ChildContent,否則會無法傳入

建立ProductList元件

<div class="card-deck">
    @if (products.Count == 0)
    {
        <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" />
    }
    else
    {
        foreach (var item in products)
        {
            <Product ProductName="@item.ProductName" Price="@item.Price">
                <img class="card-img-top" src="@item.ImgUrl" />
            </Product>
        }
    }
</div>

@code{

    List<ProductModel> products = new List<ProductModel>();

    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1000);

        products.Add(new ProductModel() { Id = 1, ProductName = "紐西蘭進口蘋果", ImgUrl = "https://www.happy-shopping.tw/img/product/236/10724_Pic.jpg", Price = 28 });
        products.Add(new ProductModel() { Id = 1, ProductName = "特選香蕉", ImgUrl = "https://www.happy-shopping.tw/img/product/236/210_Pic.jpg", Price = 18 });
        products.Add(new ProductModel() { Id = 1, ProductName = "金鑽17號鳳梨", ImgUrl = "https://www.happy-shopping.tw/img/product/236/2478_Pic.jpg", Price = 38 });

        base.OnInitialized();
    }
}
  • 使用OnInitializedAsync方式載入,設定Delay 3秒模擬讀外部資料,這個時候會顯示loading gif
  • 初始化products物件
  • 如果products count > 0,使用foreach將商品名稱和價錢透過Parameter傳入ProductCard中。
  • 將ProductCard元件展開,將<img>標籤寫在ProductCard內,ProductCard的ChildContent會接收這個<img>並顯示。

    上述是只有設定一個RenderFregment Parameter給呼叫端使用,接下來看看傳多個RenderFregment要怎麼做。

現在我們讓呼叫端可以自行決定價錢顯示的樣式,因此將Price設成RenderFregment,這時候因為有多個RenderFregment要傳,所以需指定要用的template,先將ProductCard修改如下:

<div class="card">
    @ProductImg
    <div class="card-body">
        <h5 class="card-title">@ProductName</h5>
        <p class="card-text"><span class="text-muted">Price:@Price</span></p>
    </div>
</div>

@code {
    [Parameter]
    public string ProductName { get; set; }

    [Parameter]
    public RenderFragment Price { get; set; }

    [Parameter]
    public RenderFragment ProductImg { get; set; }
}

使用端

<div class="card-deck">
    @if (products.Count == 0)
    {
        <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" />
    }
    else
    {
        foreach (var item in products)
        {
            <Product ProductName="@item.ProductName">  
                <Price>
                    <span class="text-primary font-weight-bold h4">@item.Price</span>
                </Price>
                <ProductImg>
                    <img class="card-img-top" src="@item.ImgUrl" />
                </ProductImg>
            </Product>
        }
    }
</div>

@code{

    List<ProductModel> products = new List<ProductModel>();

    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1000);

        products.Add(new ProductModel() { Id = 1, ProductName = "紐西蘭進口蘋果", ImgUrl = "https://www.happy-shopping.tw/img/product/236/10724_Pic.jpg", Price = 28 });
        products.Add(new ProductModel() { Id = 1, ProductName = "特選香蕉", ImgUrl = "https://www.happy-shopping.tw/img/product/236/210_Pic.jpg", Price = 18 });
        products.Add(new ProductModel() { Id = 1, ProductName = "金鑽17號鳳梨", ImgUrl = "https://www.happy-shopping.tw/img/product/236/2478_Pic.jpg", Price = 38 });

        base.OnInitialized();
    }
}
  • 在ProductCard template中,價錢用<span>套用bootstrap樣式,並傳入Price template
  • <img>則傳入ProductImg template
    https://ithelp.ithome.com.tw/upload/images/20201001/20130058jwDifnxLu5.jpg

在Price Template中也可以做一些邏輯判斷,例如我將商品多加個IsDiscount和SpecialPrice,如果是特價商品就顯示特價價格,修改一下ProductModel:

public class ProductModel
    {
        public int Id { get; set; }
        public string ProductName { get; set; }
        public double Price { get; set; }
        public string ImgUrl { get; set; }

        //是否為特價商品
        public bool IsDiscount { get; set; } = false;

				//原價打九折
        public double SpecialPrice
        {
            get
            {
                return Convert.ToInt32(Price * 0.9);
            }
        }
    }

ProductList

<div class="card-deck">
    @if (products.Count == 0)
    {
        <img src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" />
    }
    else
    {
        foreach (var item in products)
        {
            <Product ProductName="@item.ProductName">

                <Price>

                    //判斷是否為特價商品,顯示不同的span標籤
                    @if (item.IsDiscount)
                    {
                        <span class="text-secondary"><del>$@item.Price</del></span><span class="text-danger">  $@item.SpecialPrice</span>
                    }
                    else
                    {
                        <span class="text-dark">$@item.Price</span>
                    }
                </Price>

                <ProductImg>
                    <img class="card-img-top" src="@item.ImgUrl" />
                </ProductImg>
            </Product>
        }
    }
</div>

@code{

    List<ProductModel> products = new List<ProductModel>();

    protected override async Task OnInitializedAsync()
    {
        await Task.Delay(1000);

        products.Add(new ProductModel() { Id = 1, ProductName = "紐西蘭進口蘋果", ImgUrl = "https://www.happy-shopping.tw/img/product/236/10724_Pic.jpg", Price = 28, IsDiscount = true });
        products.Add(new ProductModel() { Id = 1, ProductName = "特選香蕉", ImgUrl = "https://www.happy-shopping.tw/img/product/236/210_Pic.jpg", Price = 18, IsDiscount = true });
        products.Add(new ProductModel() { Id = 1, ProductName = "金鑽17號鳳梨", ImgUrl = "https://www.happy-shopping.tw/img/product/236/2478_Pic.jpg", Price = 38, IsDiscount = false });

        base.OnInitialized();
    }

}

https://ithelp.ithome.com.tw/upload/images/20201001/20130058X9mcbJ9ScH.jpg


上一篇
Day 16:Cascading Paramater
下一篇
Day 18:樣板元件(2)
系列文
今晚,我想來點Blazor30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言