个人博客-推荐文章加载优化

前言

随着博客文章越来越多,那么推荐的文章也是越来越多,之前推荐文章是只推荐8篇,但是我感觉有点少,然后也是决定加一个加载按钮,也是类似与分页的效果,点击按钮可以继续加载8篇文章。

我的实现思路

同样使用X.PagedList组件去实现分页效果,通过Nuget下载即可

首先我在Service层新增了一个Task<IPagedList<Post>> GetFeaturedPostsAsync(QueryParameters param)方法

QueryParameters 类主要参数

参数类型 参数名 描述
int MaxPageSize 最大页面条目
int PageSize 页面大小
int Page 当前页面

然后该方法的实现:

/// <summary>
/// 这个查询语句会先加载 featuredPosts 表,然后使用 Include 方法加载文章表 Post,并使用 ThenInclude 方法一次性加载文章的分类和评论。
///注意,我们使用了两个 Include 方法来加载不同的关联表,并使用 ThenInclude 方法来指定要加载的关联表的属性。这样可以避免 EF Core 生成多个 SQL 查询,从而提高查询效率。
///在查询结果中,每个文章对象都包含了它的分类和评论。
/// </summary>
/// <returns></returns>
public async Task<IPagedList<Post>> GetFeaturedPostsAsync(QueryParameters param)
{
    var posts =await _myDbContext.featuredPosts
        .Include(fp => fp.Post)
        .ThenInclude(p => p.Categories)
        .Include(fp => fp.Post)
        .ThenInclude(p => p.Comments)
        .Select(fp => fp.Post)
        .OrderByDescending(o => o.CreationTime)
        .ToPagedListAsync(param.Page, param.PageSize); //分页加载数据
    return posts;
}

控制器

主要是FeaturedPosts字段去加载推荐文章,然后加载第一页,每页八条

public async Task<IActionResult> Index()
{
    HomeViewModel homeView = new HomeViewModel()
    {
        FeaturedPhotos = _fPhotoService.GetFeaturePhotos(),
        FeaturedCategories = _fCategoryService.GetFeaturedCategories(),
        TopPost = _TopPostService.GetTopOnePost(),
        FeaturedPosts = await _PostService.GetFeaturedPostsAsync(new QueryParameters
                                                                 {
                                                                     Page = 1,
                                                                     PageSize = 8,
                                                                 }),
        Links = await _linkService.GetAll(),
        Notices = await _noticeService.GetAllAsync(),
        FirstLastPost =await _articelsService.FirstLastPostAsync(),
        // MaxPost = await _articelsService.MaxPostAsync()
    };
    return View(homeView);
}

然后我在控制器新增了一个返回分布视图的方法

这个方法是从第2页开始,同样也是展示8条,该方法需要通过前端jquery ajax去调用它

public async Task<IActionResult> GetFeaturedPosts(int page = 2, int pageSize = 8)
{
    IPagedList<Post> data = await _PostService.GetFeaturedPostsAsync(new QueryParameters
                                                                     {
                                                                         Page = page,
                                                                         PageSize = pageSize,
                                                                     });
    if (data.Count == 0) {
        // 没有更多数据了,返回错误
        return NoContent();
    }

    return PartialView("Widgets/FeaturedPostCard", data);
}

前端

这里可以看到加载了一个分布视图并且传入了Model.FeaturedPosts,也就是上面控制里面的FeaturedPosts对象,他是一个IPagedList集合对象

 <div class="row mb-2" id="Home-list">
            @await Html.PartialAsync("Widgets/FeaturedPostCard",Model.FeaturedPosts) //数据在这里
</div>
<div class="row justify-content-center">
    <div class="col align-self-center text-center">
        <div class="ArcBtn" id="HomeBtn">
            <button type="button" class="btn" 
                    id="Home-more" 
                    style="background-color:#33c2ff;color:white;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);"
                    onclick="LoadHome()">加载更多</button>
        </div>
    </div>

分布视图:然后我们在分布视图中通过foreach去加载它

@using Personalblog.Migrate
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model X.PagedList.IPagedList<Personalblog.Model.Entitys.Post>

@foreach (var post in @Model)
{
    <div class="col-md-6 box">
        <div class="row g-0 border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
            <div class="col p-4 d-flex flex-column position-static">
                <strong class="d-inline-block mb-2 text-primary">@post.Categories.Name</strong>
                <h5 class="mb-0">@post.Title</h5>
                <div class="mb-1 text-muted d-flex align-items-center">
                    <span class="me-2">@post.LastUpdateTime.ToShortDateString()</span>
                    <div class="d-flex align-items-center">
                        <i class="bi bi-eye bi-sm me-1"></i>
                        <span style="font-size: 0.875rem;">@post.ViewCount</span>
                    </div>
                    <span style="width: 10px;"></span> <!-- 这里设置了一个 10px 的间距 -->
                    <div class="d-flex align-items-center">
                        <i class="bi bi-chat-square-dots bi-sm me-1"></i>
                        <span style="font-size: 0.875rem;">@post.Comments.Count</span>
                    </div>
                </div>
                <p class="card-text mb-auto">@post.Summary.Limit(50)</p>
                <a class="stretched-link"
                   asp-controller="Blog" asp-action="Post" asp-route-id="@post.Id">
                    Continue reading
                </a>
            </div>
            <div class="col-auto d-none d-lg-block">
                <img class="bd-placeholder-img" alt="" style="width:200px;height: 250px"
                     src="@Url.Action("GetRandomImage", "PicLib" ,new { seed = post.Id,Width = 800, Height = 1000})">
            </div>
        </div>
    </div>
}

上述内容只能展示8条信息,所以还需要通过ajax去调用GetFeaturedPosts接口去请求第n页的数据。

这里和之前的文章归档的实现其实是一个道理。

var currentPage = 2;
function LoadHome() {
      $.ajax({
        url: '/Home/GetFeaturedPosts',
        type: 'GET',
        data: { page: currentPage },
        success: function(data,status, xhr) {
         	 // 处理返回的数据
             // 更新当前页码
            currentPage++;
            // 将数据渲染到页面中
            $('#Home-list').append(data);
        },
        error: function() {
          // 处理错误
        }
});

实现效果

微信截图_20230620224837

结尾

合理的利用分布视图可以很方便的去展示数据。