在上一篇博客中,我们建立了story模块,并在其中完成了书写故事功能的开发。在这篇博客中,我们将实现首页上展示的故事列表,并开始开发评论功能。
十二 故事列表的开发
1 前端部分
我们需要建立一个home组件作为我们呈现故事列表的地方。我们打开cmd,输入以下命令,建立一个home组件:
ng g c home
然后,我们在app.module.ts中引入NG-ZORRO提供的标签组件,以便在之后对故事进行分类展示:
//app.module.ts
//...
import { NzTabsModule } from 'ng-zorro-antd/tabs';
//...
@NgModule({
declarations: [
//...
],
imports: [
//...
NzTabsModule,
//...
],
providers: [CookieService],
bootstrap: [AppComponent]
})
export class AppModule { }
接下来,我们打开home.component.html,输入以下代码:
<!--home.component.html-->
<nz-tabset>
<nz-tab nzTitle="全部">
<app-storylist></app-storylist>
</nz-tab>
<nz-tab nzTitle="Tab 2">
Content of Tab Pane 2
</nz-tab>
<nz-tab nzTitle="Tab 3">
Content of Tab Pane 3
</nz-tab>
</nz-tabset>
这里的app-storylist是我们稍后要建立的故事列表组件,如果想看效果的话,可以暂时把它替换为其他东西。
然后,我们将home组件加到路由列表中:
//app-routing.module.ts
//..
const routes: Routes = [
//..
{path:'',component:HomeComponent},
//..
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
这样,我们的主页就会出现一个带标签页的空白页面:

下一步,让我们继续在story模块中实现我们的storylist组件。在cmd中输入如下命令,建立storylist组件:
ng g c storylist -m story
在这个组件中我们要展示两部分数据:第一部分是故事的基本信息,第二部分是和故事有关的所有评论,因此我们需要在这个组件中定义两个接口storyDetail和commentData:
//story/storylist/commentData.ts
export interface commentData {
author:string;
content: string;
commentBody:string;
}
- author:故事作者。
- content:故事内容。
- commentBody:评论体,意思是这条评论是属于哪个故事或者评论的。
//story/storylist/storyDetail.ts
export interface storyDetail {
id:number;
author:string;
title: string;
content: string;
publishdate:string;
commentCount:string;
externalId:string;
}
- id:故事Id。
- author:故事作者
- title:故事标题
- content:故事内容
- publishdate:发布日期
- commentCount:评论数
- externalId:外部Id,如果为故事的话,其格式为’doc_‘加当前时间;如果为评论的话,其格式为’cmt_'加当前时间。此Id将在之后的评论树开发中使用。
然后,我们需要在story.module.ts中引入以下模块:
//story.moddule.ts
//..
import { NzDividerModule } from 'ng-zorro-antd/divider';
import { NzSpaceModule } from 'ng-zorro-antd/space';
import { NzCardModule } from 'ng-zorro-antd/card';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { IconDefinition } from '@ant-design/icons-angular';
import { NzCollapseModule } from 'ng-zorro-antd/collapse';
import { NzCommentModule } from 'ng-zorro-antd/comment';
import { NzAvatarModule } from 'ng-zorro-antd/avatar';
import { StarOutline, CommentOutline, LikeOutline } from '@ant-design/icons-angular/icons';
import { CommentsComponent } from './comments/comments.component';
import { CommentformComponent } from './commentform/commentform.component';
import { NzListModule } from 'ng-zorro-antd/list';
const icons: IconDefinition[] = [ StarOutline, CommentOutline, LikeOutline ];
@NgModule({
declarations: [
//..
],
imports: [
//...
NzDividerModule,
NzSpaceModule,
NzCardModule,
NzIconModule.forRoot(icons),
NzCollapseModule,
NzCommentModule,
NzAvatarModule,
NzListModule
],
exports:[StorylistComponent]
})
export class StoryModule { }
- NzDividerModule:分割线模块,用于分割文字。
- NzSpaceModule:间距模块,用于设置组件之间的间距,防止组件之间紧贴在一起。
- NzCardModule:卡片容器,可以承载文字、图片等基础内容。
- NzIconModule:NG-ZORRO提供的图标库。
- NzCollapseModule:折叠面板组件
- NzCommentModule:NG-ZORRO提供的评论框组件,是我们评论树的基础组件,提供了常用评论的基础功能,如点赞、点踩、回复,甚至还提供了一个回复用户的头像。其组件效果如下所示:

- NzAvatarModule:头像组件,就是上图左边那个人头。
- NzListModule:列表组件,以列表方式展示内容。
在引入了以上模块后,我们就可以开始编写storylist的前端部分了。打开storylist.component.html文件,输入如下代码:
<!--storylist.component.html-->
<div *ngFor="let story of storyList" >
<nz-card nzTitle="{{story.title}}" >
<div innerHtml='{{story.content}}'></div>
</nz-card>
<nz-card>
<nz-space>
<span *nzSpaceItem><i nz-icon nzType="star" nzTheme="outline"></i> 收藏</span>
<span *nzSpaceItem ><i nz-icon nzType="comment" nzTheme="outline"></i><a> 评论</a> </span>
<span *nzSpaceItem><i nz-icon nzType="like" nzTheme="outline"></i> 喜欢</span>
</nz-space>
</nz-card>
<br>
</div>
这个故事列表的结构比较简单,就是用card的方式来列出所有后端服务器返回的数据。值得注意的是,由于我们使用的是富文本编辑器来存放故事,因此在展示故事内容时要使用innerHtml属性,而不能直接将内容放在标签内部,否则会无法显示出富文本的格式。
然后,我们打开storylist.component.ts文件,开始编写前端的逻辑部分:
//storylist.component.ts
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { StoryService } from 'src/app/service/story.service';
import { storyDetail } from './storeDetail';
import { FormControl,FormGroup } from '@angular/forms';
@Component({
selector: 'app-storylist',
templateUrl: './storylist.component.html',
styleUrls: ['./storylist.component.scss']
})
export class StorylistComponent implements OnInit {
storyList:storyDetail[];
constructor(private storyService:StoryService) {
this.storyList = [];
this.showAllStory();
}
ngOnInit(): void {
}
showAllStory(){
this.storyService.showAllStory().subscribe((data:any) => {
if (data)
{
data['storylist'].forEach((element:storyDetail) => {
this.storyList.push({
'id':element['id'],
'title':element['title'],
'content':element['content'],
'author':element['author'],
'publishdate':element['publishdate'],
'commentCount':element['commentCount'],
'externalId':element['externalId']
})
});
}
})
}
}
现在的前端逻辑包含了一个storyService对象以及一个storyDetail列表,我们会在showAllStory函数中通过storyService对象拿到所有故事的数据,再将其存放到storyDetail列表中,从而在前端展示出来。
然后,我们打开story.service.ts文件,实现service中的showAllStory函数:
//service/story.service.ts
//...
@Injectable({
providedIn: 'root'
})
export class StoryService {
constructor(private http:HttpClient) { }
//...
showAllStory(){
return this.http.get('http://localhost:8000/getallstory')
}
}
这样,我们就完成了故事列表组件的前端部分。下面,让我们继续来实现故事列表的后端部分开发。
2 后端部分
我们打开story_comment_app.py,实现GetAllStory类:
# server/apps/story_comment_app/story_comment_app.py
class GetAllStory(BaseHandler):
def get(self):
allstory = session.query(Storys).all()
allstorylist = []
for story in allstory:
story_dir = {
'id':story.id,
'title':story.title,
'content':story.content,
'author':story.author,
'publishdate':story.publishDate.__str__(),
'commentCount':story.commentCount,
'externalId':story.externalId
}
allstorylist.append(story_dir)
storylist = {'storylist':allstorylist}
self.write(json.dumps(storylist))
这个函数没什么说的,当前的逻辑就是将Storys表中的所有数据都列出来,然后以字典的形式存放在list中,再将list以json的方式返回给前端即可。
最后,我们再将GetAllStory加到后端路由中:
# server/main.py
# ...
routelist = [
# ...
(r"/getallstory",GetAllStory),
# ...
]
# ...
这样,我们就完成了故事列表的开发,我们现在应该可以在首页中看到我们已发布的故事了:

接下来,让我们进入重头戏——评论系统的开发。
十三 评论系统的开发
1 评论系统结构
我们首先来看一下这个评论系统的结构:

从上图可知,在展开的评论树中,每篇故事可以有多个评论,而对于每个评论来说,又可以分别对其进行新的评论,并以缩进方式显示在其下方。这就需要我们实现一个嵌套的组件,这个组件里既要包含已发布的评论内容,又要包含发布新评论的表单。因此,我们评论系统的结构如下图所示:

在图中,每个Comment都包含两部分:其下的子评论以及发表评论的表单。因此,我们的评论系统要由两个组件组成:其一为显示子评论的list,其二为发布评论的表单。显示子评论的List会以递归的方式从后端获取到该评论下的所有子评论,包括孙子评论;而发布评论的表单功能比较单一,只是一个普通的表单。这样,我们将这两个组件组合起来,便可以实现我们的评论树功能。
在这期博客中,我们实现了故事列表功能,并为大家介绍了评论系统的结构。在下一篇博客中,将继续带领大家开发评论系统,并介绍angular中模板的相关知识,希望大家继续关注~

本文详细介绍了如何在Angular应用中实现故事列表与评论功能,包括前端组件设计、数据交互与后端API开发。通过Ng-ZORRO组件和自定义模块,展示了如何展示故事详情、评论数据及实现点赞等功能。
&spm=1001.2101.3001.5002&articleId=120624128&d=1&t=3&u=812ad18633d748bfa9b3ac8afb904db8)

被折叠的 条评论
为什么被折叠?



