首頁  >  文章  >  web前端  >  實例詳解Angular實現類似部落格評論的遞歸顯示及取得回覆評論的數據

實例詳解Angular實現類似部落格評論的遞歸顯示及取得回覆評論的數據

小云云
小云云原創
2017-12-26 13:55:072317瀏覽

本文主要給大家介紹了關於Angular如何實現類似博客評論的遞歸顯示及獲取回复評論的數據的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

前言

我們在一些技術部落格中會經常看到很多遞歸評論,也即是我們可以回覆博友的評論,且界面很美觀,有梯度的顯示格式,日前在空餘時間寫類似的demo,所以記錄下來,可以給需要的人一些借鏡的作用。
好了,廢話少說,直奔主題。 。 。

思路

我們在寫後台程式的時候,常常會遇到產生類似樹的這種資料結構,我們直覺就是使用遞歸的方法來實現,起初我也是這麼想的,就是寫一個Angular4 的遞歸方法,組成一個字串,然後在介面顯示,類似下面程式碼

@Component({
 selector: "comment",
 template: '{{ comments }}'
})
export class CommentComponent {

 public comments: string = "";

 generateComment(Comment comment) {
 this.comments = this.comments + "<p>" + comment.content + "</p>";
 if (comment.pComment != null) {
  generateComment(comment.pComment);
 }
 }
}

很天真的以為可以了,結果一試,標籤不會被解析,才想起已經過了解析標籤的過程了。 。 。

後來想著,現在的前端框架都是以元件化自稱, Angular4 也不例外,那麼一個Component 可以嵌入任何Component,那肯定可以嵌入自己,也就有了類似遞歸的概念了,想到這立馬試試。 。 。

具體實現

思路是這樣子,我定義了資料的格式,是每個評論下面有一個子評論數組,而不是每個評論有一個父評論,資料格式如下:

"comments": 
  [
  {
   "id": 1,
   "username": "James1",
   "time": "2017-07-09 21:02:21",
   "content": "哈哈哈1<h1>哈哈哈</h1>",
   "status": 1,
   "email": "1xxxx@xx.com",
   "cComments": [
    {
    "id": 2,
    "username": "James2",
    "time": "2017-07-09 21:02:22",
    "content": "哈哈哈2",
    "status": 1,
    "email": "2xxxx@xx.com",
    "cComments": null
   }
   ]
  }
  ]

CommentComponent 元件實作了評論模組,但是遞歸評論並不在這個元件實現,而是在子元件CommentViewComponent 中實現,因為CommentComponent 還包括一個輸入評論的文字方塊。

評論總模組ComponentComponent 程式碼:

comment.component.ts

@Component({
 selector: 'comment',
 templateUrl: './comment.component.html',
 styleUrls: ['./comment.component.css']
})
export class CommentComponent implements OnInit {

 @Input()
 public comments: Comment[];

 ngOnInit(): void {
 }
}

comment.component.html

<p class="container font-small">
 <p class="row">
 <p class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

  <comment-view [comments]="comments"></comment-view>

  <p class="well" id="comment">
  <h4>{{ 'comment.leaveComment' | translate }}</h4>
  <form role="form">
   <p class="form-group">
   <input type="hidden" [(ngModel)]="id" name="id">
   <textarea [(ngModel)]="content" name="content" class="form-control" rows="5"></textarea>
   </p>
   <button type="submit" class="btn btn-primary">Submit</button>
  </form>
  </p>
 </p>
 </p>
</p>

comment.component.css

.media {
 font-size: 14px;
}

.media-object {
 padding-left: 10px;
}

子模組ComponentViewComponent 程式碼:

component-view.component.ts

@Component({
 selector: 'comment-view',
 templateUrl: './comment-view.component.html',
 styleUrls: ['./comment-view.component.css']
})
export class CommentViewComponent implements OnInit {
 @Input()
 public comments: Comment[];

 constructor(private router: Router,
    private activateRoute: ActivatedRoute ) {
 }

 ngOnInit(): void {
 }
}

component-view.component.html

<p *ngFor="let comment of comments">
 <p class="media">
 <p class="pull-left">
  <span class="media-object"></span>
 </p>
 <p class="media-body">
  <h4 class="media-heading">{{ comment.username }}
  <small class="pull-right">{{ comment.time }} | <a href="#" rel="external nofollow" >{{ 'comment.reply' | translate }}</a></small>
  </h4>
  {{ comment.content }}
  <hr>
  <comment-view *ngIf="comment.cComments != null" [comments]="comment.cComments"></comment-view>
 </p>
 </p>
</p>

comonent-view.component.css

.media {
 font-size: 14px;
}

.media-object {
 padding-left: 10px;
}

結果

這時的展示結果如下圖所示:

#上面只是說明如何實作註解梯形顯示,在部落格評論中我們經常看到可以回覆某一則評論,本文講述如何實現點擊某一評論的回覆按鈕後,取得該評論的內容並顯示在輸入框中。類似CSDN 部落格評論一樣,點擊回覆後輸入框自動添加了[reply]u011642663[/reply]

思路

依據上一篇文章中的評論梯形顯示,我們還需要實現點擊回覆後,螢幕自動到達輸入框位置,並且取得了點擊回覆的評論的資訊。首先分解這個功能點,在專案中我們也會經常分解功能點,這個功能點有2 個小點:一是在每個評論中加上[回覆] 按鈕,點擊回復後跳到輸入框位置;二是點擊回覆後,取得到點擊回覆的那條評論的資訊。下面我們一一解決。

跳到輸入框

我們接觸前段第一個語言便是 HTML,我們知道 HTML 中有一個 # 定位,下面程式碼簡單解釋一下。

假設這個HTML 程式碼檔案是index.html

<html>
 <head>
 </head>
 <body>
 <a href="index.html#pointer" rel="external nofollow" >Click me to pointer</a>
 <p id="pointer">
  <h1>哈哈哈哈</h1>
 </p>
 </body>
</html>

上面程式碼只要點擊Click me to pointer 這個鏈接,頁面就會跳到id=”pointer” 這個p 的位置。所以我們在實作這個點擊回覆跳到輸入框中就可以使用這個方法。

我們在comment-component.html 中將評論輸入框加入id=”comment”,接下來就是路徑拼接的問題了,我們可以透過Angular 的Router 的url 來取得本頁面的路徑,然後在這個路徑後面加入#comment 就可以實現跳轉了,下面是實現這個跳轉功能的程式碼

新增id=”comment”

#comment-component.html

<!-- Comment -->
<p class="container font-small">
 <p class="row">
 <p class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

  <comment-view [comments]="comments" (contentEvent)="getReplyComment($event)" ></comment-view>

  <p class="well" id="comment">
  <h4>{{ 'comment.leaveComment' | translate }}</h4>
  <form role="form">
   <p class="form-group">
   <input type="hidden" [(ngModel)]="id" name="id">
   <textarea [(ngModel)]="content" name="content" class="form-control" rows="5"></textarea>
   </p>
   <button type="submit" class="btn btn-primary">Submit</button>
  </form>
  </p>
 </p>
 </p>
</p>

新增透過路由取得目前頁面URL

comment-view.component.ts

@Component({
 selector: 'comment-view',
 templateUrl: './comment-view.component.html',
 styleUrls: ['./comment-view.component.css']
})
export class CommentViewComponent implements OnInit {
 @Input()
 public comments: Comment[];

 // 用于跳转到回复输入框的url拼接
 public url: string = "";

 constructor(private router: Router,
    private activateRoute: ActivatedRoute ) {
 }

 ngOnInit(): void {
 this.url = this.router.url;
 this.url = this.url.split("#")[0];
 this.url = this.url + "#comment";
 }
}

新增連結href=」「

comment-view.component .html

<p *ngFor="let comment of comments">
 <p class="media">
 <p class="pull-left">
  <span class="media-object"></span>
 </p>
 <p class="media-body">
  <h4 class="media-heading">{{ comment.username }}
  <small class="pull-right">{{ comment.time }} | <a href="{{url}}" rel="external nofollow" rel="external nofollow" (click)="reply(comment)" >{{ 'comment.reply' | translate }}</a></small>
  </h4>
  {{ comment.content }}
  <hr>
  <comment-view *ngIf="comment.cComments != null" [comments]="comment.cComments" (contentEvent)="transferToParent($event)"></comment-view>
 </p>
 </p>
</p>

這實現了頁面跳躍的功能點,接下來實現回應的評論的資訊。

取得回覆的評論訊息

有人会说获取回复的评论信息,这不简单么?加个 click 事件不就行了。还记得上一篇文章咱们是如何实现梯形展示评论的么?咱们是通过递归来实现的,怎么添加 click 事件让一个不知道嵌了多少层的组件能够把评论信息传给父组件?首先不具体想怎么实现,我们这个思路是不是对的:把子组件的信息传给父组件?答案是肯定的,我们就是要把不管嵌了多少层的子组件的信息传给 comment.component.ts 这个评论模块的主组件。
Angular 提供了 @Output 来实现子组件向父组件传递信息,我们在 comment-view.component.ts 模块中添加 @Output 向每个调用它的父组件传信息,我们是嵌套的,这样一层一层传出来,直到传给 comment-component.ts 组件。我们看代码怎么实现。

实现代码

comment-view.component.ts

@Component({
 selector: 'comment-view',
 templateUrl: './comment-view.component.html',
 styleUrls: ['./comment-view.component.css']
})
export class CommentViewComponent implements OnInit {
 @Input()
 public comments: Comment[];
 // 点击回复时返回数据
 @Output()
 public contentEvent: EventEmitter<Comment> = new EventEmitter<Comment>();
 // 用于跳转到回复输入框的url拼接
 public url: string = "";

 constructor(private router: Router,
    private activateRoute: ActivatedRoute ) {
 }

 ngOnInit(): void {
 this.url = this.router.url;
 this.url = this.url.split("#")[0];
 this.url = this.url + "#comment";
 }

 reply(comment: Comment) {
 this.contentEvent.emit(comment);
 }

 transferToParent(event) {
 this.contentEvent.emit(event);
 }
}

comment-view.component.html

<p *ngFor="let comment of comments">
 <p class="media">
 <p class="pull-left">
  <span class="media-object"></span>
 </p>
 <p class="media-body">
  <h4 class="media-heading">{{ comment.username }}
  <small class="pull-right">{{ comment.time }} | <a href="{{url}}" rel="external nofollow" rel="external nofollow" (click)="reply(comment)" >{{ 'comment.reply' | translate }}</a></small>
  </h4>
  {{ comment.content }}
  <hr>
  <comment-view *ngIf="comment.cComments != null" [comments]="comment.cComments" (contentEvent)="transferToParent($event)"></comment-view>
 </p>
 </p>
</p>

comment.component.ts

@Component({
 selector: 'comment',
 templateUrl: './comment.component.html',
 styleUrls: ['./comment.component.css']
})
export class CommentComponent implements OnInit {

 @Input()
 public comments: Comment[];

 // 要回复的评论
 public replyComment: Comment = new Comment();

 public id: number = 0;
 public content: string = "";

 ngOnInit(): void {
 }

 getReplyComment(event) {
 this.replyComment = event;
 this.id = this.replyComment.id;
 this.content = "[reply]" + this.replyComment.username + "[reply]\n";
 }
}

comment.component.html

<!-- Comment -->
<p class="container font-small">
 <p class="row">
 <p class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

  <comment-view [comments]="comments" (contentEvent)="getReplyComment($event)" ></comment-view>

  <p class="well" id="comment">
  <h4>{{ 'comment.leaveComment' | translate }}</h4>
  <form role="form">
   <p class="form-group">
   <input type="hidden" [(ngModel)]="id" name="id">
   <textarea [(ngModel)]="content" name="content" class="form-control" rows="5"></textarea>
   </p>
   <button type="submit" class="btn btn-primary">Submit</button>
  </form>
  </p>
 </p>
 </p>
</p>

解释一下代码逻辑:

我们在 comment-view.component.ts 添加以下几点:

  • 定义了@Output() contentEvent

  • 添加了reply(comment: Comment) 事件在点击回复的时候触发的,触发的时候 contentEvent 将 comment 传到父模块

  • 添加 transferToParent(event) 是接受子组件传来的 event, 并且继续将 event 传到父组件

在 comment.component.ts 中定义了 getReplyComment(event) 方法,该方法接收子组件传递来的评论信息,并将信息显示在页面上。大功告成。。。

效果图

相关推荐:

怎样用PHP开发博客评论系统!解决办法

博客评论回访者跟踪

如何PHP制作简易博客

以上是實例詳解Angular實現類似部落格評論的遞歸顯示及取得回覆評論的數據的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn