基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(四)


系列文章

  1. 基於 abp vNext 和 .NET Core 開發博客項目 - 使用 abp cli 搭建項目
  2. 基於 abp vNext 和 .NET Core 開發博客項目 - 給項目瘦身,讓它跑起來
  3. 基於 abp vNext 和 .NET Core 開發博客項目 - 完善與美化,Swagger登場
  4. 基於 abp vNext 和 .NET Core 開發博客項目 - 數據訪問和代碼優先
  5. 基於 abp vNext 和 .NET Core 開發博客項目 - 自定義倉儲之增刪改查
  6. 基於 abp vNext 和 .NET Core 開發博客項目 - 統一規范API,包裝返回模型
  7. 基於 abp vNext 和 .NET Core 開發博客項目 - 再說Swagger,分組、描述、小綠鎖
  8. 基於 abp vNext 和 .NET Core 開發博客項目 - 接入GitHub,用JWT保護你的API
  9. 基於 abp vNext 和 .NET Core 開發博客項目 - 異常處理和日志記錄
  10. 基於 abp vNext 和 .NET Core 開發博客項目 - 使用Redis緩存數據
  11. 基於 abp vNext 和 .NET Core 開發博客項目 - 集成Hangfire實現定時任務處理
  12. 基於 abp vNext 和 .NET Core 開發博客項目 - 用AutoMapper搞定對象映射
  13. 基於 abp vNext 和 .NET Core 開發博客項目 - 定時任務最佳實戰(一)
  14. 基於 abp vNext 和 .NET Core 開發博客項目 - 定時任務最佳實戰(二)
  15. 基於 abp vNext 和 .NET Core 開發博客項目 - 定時任務最佳實戰(三)
  16. 基於 abp vNext 和 .NET Core 開發博客項目 - 博客接口實戰篇(一)
  17. 基於 abp vNext 和 .NET Core 開發博客項目 - 博客接口實戰篇(二)
  18. 基於 abp vNext 和 .NET Core 開發博客項目 - 博客接口實戰篇(三)
  19. 基於 abp vNext 和 .NET Core 開發博客項目 - 博客接口實戰篇(四)
  20. 基於 abp vNext 和 .NET Core 開發博客項目 - 博客接口實戰篇(五)
  21. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(一)
  22. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(二)
  23. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(三)
  24. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(四)
  25. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(五)
  26. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(六)
  27. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(七)
  28. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(八)
  29. 基於 abp vNext 和 .NET Core 開發博客項目 - Blazor 實戰系列(九)
  30. 基於 abp vNext 和 .NET Core 開發博客項目 - 終結篇之發布項目

上一篇完成了博客的分頁查詢文章列表頁面的數據綁定和分頁功能,本篇將繼續完成剩下的幾個頁面。

在開始主題之前重新解決上一篇的最后一個問題,當點擊了頭部組件的/posts鏈接時直接強制刷新了頁面,經過查看文檔和實踐有了更好的解決方案。

先將頭部組件Header.razor中的NavLink恢復成<NavLink class="menu-item" href="posts">Posts</NavLink>,不需要點擊事件了。

然后在Posts.razor中添加生命周期函數OnParametersSetAsync(),在初始化完成后執行。

/// <summary>
/// 初始化完成后執行
/// </summary>
/// <returns></returns>
protected override async Task OnParametersSetAsync()
{
    if (!page.HasValue)
    {
        page = 1;
        await RenderPage(page);
    }
}

判斷當前page參數是否有值,有值的話說明請求肯定是來自於翻頁,當page沒有值的時候就說明是頭部的菜單點進來的。那么此時給page賦值為1,調用API加載數據即可。

分類列表

Categories.razor是分類列表頁面,上篇文章已經實現了從API獲取數據的方法,所以這里就很簡單了,指定接受類型,然后在生命周期初始化OnInitializedAsync()中去獲取數據。

@code{
    /// <summary>
    /// categories
    /// </summary>
    private ServiceResult<IEnumerable<QueryCategoryDto>> categories;

    /// <summary>
    /// 初始化
    /// </summary>
    protected override async Task OnInitializedAsync()
    {
        // 獲取數據
        categories = await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryCategoryDto>>>($"/blog/categories");
    }
}

當獲取到數據的時候進行綁定,沒有數據的時候還是顯示加載中的組件<Loading />讓他轉圈圈。

@if (categories == null)
{
    <Loading />
}
else
{
    <div class="container">
        <div class="post-wrap categories">
            <h2 class="post-title">-&nbsp;Categories&nbsp;-</h2>
            <div class="categories-card">
                @if (categories.Success && categories.Result.Any())
                {
                    @foreach (var item in categories.Result)
                    {
                        <div class="card-item">
                            <div class="categories">
                                <a href="/category/@item.DisplayName/">
                                    <h3>
                                        <i class="iconfont iconcode" style="padding-right:3px"></i>
                                        @item.CategoryName
                                    </h3>
                                    <small>(@item.Count)</small>
                                </a>
                            </div>
                        </div>
                    }
                }
                else
                {
                    <ErrorTip />
                }
            </div>
        </div>
    </div>
}

直接循環返回的數據列表categories.Result,綁定數據就好,當獲取失敗或者沒有返回數據的時候顯示錯誤提示組件<ErrorTip />

1

標簽列表

Categories.razor是標簽列表頁面,和分類列表HTML結構差不多一樣的,除了返回類型和接口地址不一樣,將上面代碼復制過來改改即可。

@code{
    /// <summary>
    /// tags
    /// </summary>
    private ServiceResult<IEnumerable<QueryTagDto>> tags;

    /// <summary>
    /// 初始化
    /// </summary>
    protected override async Task OnInitializedAsync()
    {
        // 獲取數據
        tags = await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryTagDto>>>($"/blog/tags");
    }
}
@if (tags == null)
{
    <Loading />
}
else
{
    <div class="container">
        <div class="post-wrap tags">
            <h2 class="post-title">-&nbsp;Tags&nbsp;-</h2>
            <div class="tag-cloud-tags">
                @if (tags.Success && tags.Result.Any())
                {
                    @foreach (var item in tags.Result)
                    {
                        <a href="/tag/@item.DisplayName/">@item.TagName<small>(@item.Count)</small></a>
                    }
                }
                else
                {
                    <ErrorTip />
                }
            </div>
        </div>
    </div>
}

2

友鏈列表

FriendLinks.razor是友情鏈接列表頁面,實現方式和上面兩個套路一模一樣。

@code {
    /// <summary>
    /// friendlinks
    /// </summary>
    private ServiceResult<IEnumerable<FriendLinkDto>> friendlinks;

    /// <summary>
    /// 初始化
    /// </summary>
    protected override async Task OnInitializedAsync()
    {
        // 獲取數據
        friendlinks = await Http.GetFromJsonAsync<ServiceResult<IEnumerable<FriendLinkDto>>>($"/blog/friendlinks");
    }
}
@if (friendlinks == null)
{
    <Loading />
}
else
{
    <div class="container">
        <div class="post-wrap categories">
            <h2 class="post-title">-&nbsp;FriendLinks&nbsp;-</h2>
            <div class="categories-card">
                @if (friendlinks.Success && friendlinks.Result.Any())
                {
                    @foreach (var item in friendlinks.Result)
                    {
                        <div class="card-item">
                            <div class="categories">
                                <a target="_blank" href="@item.LinkUrl">
                                    <h3>@item.Title</h3>
                                </a>
                            </div>
                        </div>
                    }
                }
                else
                {
                    <ErrorTip />
                }
            </div>
        </div>
    </div>
}

3

文章列表(分類)

Posts.Category.razor是根據分類查詢文章列表頁面,他接受一個參數name,我們要根據name去API查詢數據然后綁定頁面即可。

這里的參數name實際上就是從標簽列表傳遞過來的DisplayName的值,它是一個比較友好的名稱,我們還要通過這個值去查詢真正的分類名稱進行展示,所以這里需要調用兩個API,這點在設計API的時候沒有考慮好,我們其實可以將這兩個API合並變成一個,后續再進行優化吧,這里就請求兩次。

添加兩個接收參數:分類名稱和返回的文章列表數據。

/// <summary>
/// 分類名稱
/// </summary>
private string categoryName;

/// <summary>
/// 文章列表數據
/// </summary>
private ServiceResult<IEnumerable<QueryPostDto>> posts;

然后在OnInitializedAsync()初始化方法中調用API獲取數據,賦值給變量。

/// <summary>
/// 初始化
/// </summary>
protected override async Task OnInitializedAsync()
{
    // TODO:獲取數據,可以在API中合並這兩個請求。
    var category = await Http.GetFromJsonAsync<ServiceResult<string>>($"/blog/category?name={name}");
    posts = await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryPostDto>>>($"/blog/posts/category?name={name}");

    if (category.Success)
    {
        categoryName = category.Result;
    }
}

有了數據,直接在頁面上進行循環綁定。

@if (posts == null)
{
    <Loading />
}
else
{
    <div class="container">
        <div class="post-wrap tags">
            @if (categoryName != null)
            {
                <h2 class="post-title">-&nbsp;Category&nbsp;·&nbsp;@categoryName&nbsp;-</h2>
            }
        </div>
        <div class="post-wrap archive">
            @if (posts.Success && posts.Result.Any())
            {
                @foreach (var item in posts.Result)
                {
                    <h3>@item.Year</h3>
                    @foreach (var post in item.Posts)
                    {
                        <article class="archive-item">
                            <NavLink href="@("/post"+post.Url)">@post.Title</NavLink>
                            <span class="archive-item-date">@post.CreationTime</span>
                        </article>
                    }
                }
            }
            else
            {
                <ErrorTip />
            }
        </div>
    </div>
}

4

文章列表(標簽)

Posts.Tag.razor是根據標簽查詢文章列表,這個和分類查詢文章列表實現方式一樣,直接上代碼。

@code {
    /// <summary>
    /// 標簽名稱參數
    /// </summary>
    [Parameter]
    public string name { get; set; }

    /// <summary>
    /// 標簽名稱
    /// </summary>
    private string tagName;

    /// <summary>
    /// 文章列表數據
    /// </summary>
    private ServiceResult<IEnumerable<QueryPostDto>> posts;

    /// <summary>
    /// 初始化
    /// </summary>
    protected override async Task OnInitializedAsync()
    {
        // TODO:獲取數據,可以在API中合並這兩個請求。
        var tag = await Http.GetFromJsonAsync<ServiceResult<string>>($"/blog/tag?name={name}");
        posts = await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryPostDto>>>($"/blog/posts/tag?name={name}");

        if (tag.Success)
        {
            tagName = tag.Result;
        }
    }
}
@if (posts == null)
{
    <Loading />
}
else
{
    <div class="container">
        <div class="post-wrap tags">
            @if (tagName != null)
            {
                <h2 class="post-title">-&nbsp;Tag&nbsp;·&nbsp;@tagName&nbsp;-</h2>
            }
        </div>
        <div class="post-wrap archive">
            @if (posts.Success && posts.Result.Any())
            {
                @foreach (var item in posts.Result)
                {
                    <h3>@item.Year</h3>
                    @foreach (var post in item.Posts)
                    {
                        <article class="archive-item">
                            <NavLink href="@("/post"+post.Url)">@post.Title</NavLink>
                            <span class="archive-item-date">@post.CreationTime</span>
                        </article>
                    }
                }
            }
            else
            {
                <ErrorTip />
            }
        </div>
    </div>
}

5

以上完成了以上幾個頁面的數據綁定,頁面之間的跳轉已經關聯起來了,然后還剩下文章詳情頁,大家可以先自己動手完成它,今天就到這里,未完待續...

開源地址:https://github.com/Meowv/Blog/tree/blog_tutorial


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM