基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)

系列文章

  1. 使用 abp cli 搭建项目

  2. 给项目瘦身,让它跑起来

  3. 完善与美化,Swagger登场

  4. 数据访问和代码优先

  5. 自定义仓储之增删改查

  6. 统一规范API,包装返回模型

  7. 再说Swagger,分组、描述、小绿锁

  8. 接入GitHub,用JWT保护你的API

  9. 异常处理和日志记录

  10. 使用Redis缓存数据

  11. 集成Hangfire实现定时任务处理

  12. 用AutoMapper搞定对象映射

  13. 定时任务最佳实战(一)

  14. 定时任务最佳实战(二)

  15. 定时任务最佳实战(三)

  16. 博客接口实战篇(一)

  17. 博客接口实战篇(二)

  18. 博客接口实战篇(三)

  19. 博客接口实战篇(四)

  20. 博客接口实战篇(五)

  21. Blazor实战系列(一)

  22. Blazor实战系列(二)

  23. Blazor实战系列(三)


上一篇完成了博客的分页查询文章列表页面的数据绑定和分页功能,本篇将继续完成剩下的几个页面。

在开始主题之前重新解决上一篇的最后一个问题,当点击了头部组件的/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 />

标签列表

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>
}

友链列表

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>
}

文章列表(分类)

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>
}

文章列表(标签)

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>
}

以上完成了以上几个页面的数据绑定,页面之间的跳转已经关联起来了,然后还剩下文章详情页,大家可以先自己动手完成它,今天就到这里,未完待续...

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符串相关

文章目录字符串基础字符串的存储标准库字符串匹配单串匹配多串匹配其他类型的字符串匹配问题字符串哈希Hash 的实现Hash 的分析与改进错误率多次询问子串哈希Hash 的应用字符串匹配允许 k次失配的字符串匹配最长回文子串最长公共子字符串确定字符串中不同子字符串的数量字典树 …

C#9.0 终于来了,您还学的动吗? 带上VS一起解读吧!

一&#xff1a;背景1. 讲故事好消息&#xff0c;.NET 5.0 终于在2020年6月10日发布了第五个预览版&#xff0c;眼尖的同学一定看到了在这个版本中终于支持了 C# 9.0&#xff0c;此处有掌声&#xff0c;太好了&#xff01;&#xff01;&#xff01;.Net5官方链接可以看到目前的C…

.NET Core 反射获取所有控制器及方法上特定标签

有个需求&#xff0c;就是在. NET Core中&#xff0c;我们想在项目 启动时&#xff0c;获取LinCmsAuthorizeAttribute这个特性标签所有出现的地方&#xff0c;把他的参数&#xff0c;放入一个集合并缓存起来&#xff0c;以便后面使用此数据用于权限验证。我们通过反射获取所有控…

[JavaWeb-Servlet]Servlet的体系结构

Servlet的体系结构 Servlet -- 接口|GenericServlet -- 抽象类|HttpServlet -- 抽象类* GenericServlet&#xff1a;将Servlet接口中其他的方法做了默认空实现&#xff0c;只将service()方法作为抽象* 将来定义Servlet类时&#xff0c;可以继承GenericServlet&#xff0c;实现…

将数据从 SQL Server 导入 Azure Storage Table

点击上方蓝字关注“汪宇杰博客”导语最近有个需求要将数据存储从 SQL Server 数据库切换到 Azure Storage 中的 Table。然而不管是 SSMS 还是 Azure Portal 都没有提供直接的导入功能&#xff0c;是不是又想自己写程序去导数据了&#xff1f;其实不用&#xff01;没有点过数据库…

[JavaWeb-HTTP]HTTP概念

HTTP&#xff1a; * 概念&#xff1a;Hyper Text Transfer Protocol 超文本传输协议* 传输协议&#xff1a;定义了&#xff0c;客户端和服务器端通信时&#xff0c;发送数据的格式* 特点&#xff1a;1. 基于TCP/IP的高级协议2. 默认端口号:803. 基于请求/响应模型的:一次请求对…

【完整目录】每天5分钟用C#学习数据结构

【基础知识】| 作者 / Edison Zhou这是恰童鞋骚年的第250篇原创内容不知不觉&#xff0c;每天5分钟学习数据结构就更新完了&#xff0c;本篇将该系列所有文章整理起来作为一个目录&#xff0c;方便你的快速阅读。1线性表线性表是最简单也是在编程当中使用最多的一种数据结构。例…

.NET 5 开发WPF - 美食应用登录UI设计

点击上方“Dotnet9”添加关注哦Demo演示&#xff1a;演示动画你的时间宝贵&#xff0c;不想看啰嗦的文字&#xff0c;可直接拉到文末下载源码&#xff01;1. 新建项目站长开发环境&#xff1a;VS 2019企业版 16.70.NET 5 Preview 5.NET 5 WPF 项目模板和 .NET Core 3.1 WPF 项目…

基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五)

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

C#9.0 终于来了,带你一起解读 nint 和 Pattern matching 两大新特性玩法

一&#xff1a;背景1. 讲故事上一篇C#9.0 终于来了&#xff0c;您还学的动吗&#xff1f; 带上VS一起解读吧&#xff01;跟大家聊到了Target-typed new 和 Lambda discard parameters&#xff0c;看博客园和公号里的阅读量都达到了新高&#xff0c;甚是欣慰&#xff0c;不管大家…

软件设计模式期末大作业——可乐商城管理系统

文章目录设计模式大作业软 件 设 计 模 式 任 务 书设计要求&#xff1a;学生应完成的工作&#xff1a;1. 应用场景描述2. 设计模式选择3. 实现语言与工具参考文献阅读&#xff1a;工作计划&#xff1a;一、系统目标1. 设计目的2. 需求描述二、 系统模式选择1.需求分析2.选用设…

深度解读Microsoft Build 2020:提升开发效率,优化开发环境

Microsoft Build 2020在众多新产品与技术发布中圆满落幕但身为开发技术人深知技术世界的更迭、求索却从未止步唯有不断提升自身技能栈创新方能从技术浮沉中获得更多养分让技术予力世界更有温度Microsoft Build 2020大会后&#xff0c; Visual Studio Family 和 .NET 成为众多开…

[JavaWeb]web相关概念回顾

web相关概念回顾 1. 软件架构1. C/S&#xff1a;客户端/服务器端2. B/S&#xff1a;浏览器/服务器端2. 资源分类1. 静态资源&#xff1a;所有用户访问后&#xff0c;得到的结果都是一样的&#xff0c;称为静态资源.静态资源可以直接被浏览器解析* 如&#xff1a; html,css,Jav…

Github 数据洞察之复杂信息网络

摘要&#xff1a;开源协作是数字化时代的必备技能&#xff0c;而背后的开发行为分析&#xff0c;能够让你看到一幅开源世界的全景图&#xff1b;2020年2月&#xff0c;X-lab 开放实验室联合InfoQ发布了《GitHub 2019 数字年报》&#xff0c;收到了业界的一致好评。数据科学与工…

2020年,.NET Core起飞在即,最强日志分析ELK还不会?

近期.NET社区迎来一系列利好&#xff1a;1 Build2020&#xff0c;微软发布多款产品赋能.NET开发者&#xff0c;比以往任何时候都更贴近开发者&#xff1b;2 TechEmpower第19轮编程语言框架性能排行榜&#xff0c;Asp.Net Core成为主流Web框架第一&#xff1b;3 Stackoverflow 2…

[JavaWeb-HTTP]request对象和response对象的原理

request对象和response对象的原理 1. request和response对象是由服务器创建的。我们来使用它们2. request对象是来获取请求消息&#xff0c;response对象是来设置响应消息

时间序列神器之争:prophet VS lstm

一、需求背景我们福禄网络致力于为广大用户提供智能化充值服务&#xff0c;包括各类通信充值卡&#xff08;比如移动、联通、电信的话费及流量充值&#xff09;、游戏类充值卡&#xff08;比如王者荣耀、吃鸡类点券、AppleStore充值、Q币、斗鱼币等&#xff09;、生活服务类&am…

docker registry 镜像同步

docker registry 镜像同步Intro之前我们的 docker 镜像是保存在 Azure 的 Container Registry 里的&#xff0c;最近我们自己搭建了一个 docker registry&#xff0c;我们想把之前保存的 Azure 的 Container Registry 的 docker 镜像同步到我们自己的 docker registry 里实现思…

[数据结构-严蔚敏版]P37定义一个带头结点的线性链表

大家如果发现代码有错误&#xff0c;麻烦评论告知一下!!! 代码我已经发现存在部分错误&#xff0c;等有时间我再进行修正。目前存在错误:mergeList_L函数有问题! 代码如下: #include <iostream> using namespace std;typedef struct LNode {int data;LNode *next; }*L…

.NET Core加解密实战系列之——RSA非对称加密算法

简介加解密现状&#xff0c;编写此项目的背景&#xff1a;需要考虑系统环境兼容性问题&#xff08;Linux、Windows&#xff09;语言互通问题&#xff08;如C#、Java&#xff09;网上资料版本不一、不全面.NET官方库密码算法提供不全面&#xff0c;很难针对其他语言&#xff08;…