溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Angular如何實現(xiàn)類似博客評論的遞歸顯示

發(fā)布時間:2021-06-29 13:51:39 來源:億速云 閱讀:213 作者:小新 欄目:web開發(fā)

這篇文章給大家分享的是有關Angular如何實現(xiàn)類似博客評論的遞歸顯示的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

思路

我們在寫后臺程序的時候,經常會遇到生成類似樹的這種數(shù)據(jù)結構,我們直覺就是使用遞歸的方法來實現(xiàn),起初我也是這么想的,就是寫一個 Angular4 的遞歸方法,組成一個字符串,然后在界面顯示,類似下面代碼

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

 public comments: string = "";

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

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

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

具體實現(xiàn)

思路是這樣子,我定義了數(shù)據(jù)的格式,是每個評論下面有一個子評論數(shù)組,而不是每個評論有一個父評論,數(shù)據(jù)格式如下:

"comments": 
  [
  {
   "id": 1,
   "username": "James1",
   "time": "2017-07-09 21:02:21",
   "content": "哈哈哈1<h2>哈哈哈</h2>",
   "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 組件實現(xiàn)了評論模塊,但是遞歸評論并不在這個組件實現(xiàn),而是在子組件 CommentViewComponent 實現(xiàn),因為 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

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

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

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

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

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

comonent-view.component.css

.media {
 font-size: 14px;
}

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

結果

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

Angular如何實現(xiàn)類似博客評論的遞歸顯示

上面只是說明了如何實現(xiàn)評論梯形顯示,在博客評論中我們經??吹娇梢曰貜湍骋粭l評論,本文講述如何實現(xiàn)點擊某一條評論的回復按鈕后,獲取該條評論的內容并顯示在輸入框中。類似 CSDN 博客評論一樣,點擊回復后輸入框自動添加了 [reply]u011642663[/reply]

思路

依據(jù)上一篇文章中的評論梯形顯示,我們還需要實現(xiàn)點擊回復后,屏幕自動到達輸入框位置,并且獲取了點擊回復的評論的信息。首先分解一下這個功能點,在項目中我們也會經常分解功能點,這個功能點有 2 個小點:一是在每條評論中加上 [回復] 按鈕,點擊回復后跳到輸入框位置;二是點擊回復后,獲取到點擊回復的那條評論的信息。下面我們一一解決。

跳轉到輸入框

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

假設這個 HTML 代碼文件是 index.html

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

上面代碼只要點擊 Click me to pointer 這個鏈接,頁面就會跳到 id=”pointer” 這個 div 的位置。所以我們在實現(xiàn)這個點擊回復跳轉到輸入框中就可以使用這個方法。

我們在 comment-component.html 中將評論輸入框加入 id=”comment”,接下來就是路徑拼接的問題了,我們可以通過 Angular 的 Router 的 url 來獲取本頁面的路徑,然后在這個路徑后面加入 #comment 就可以實現(xiàn)跳轉了,下面是實現(xiàn)這個跳轉功能的代碼

添加 id=”comment”

comment-component.html

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

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

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

添加通過路由獲取當前頁面 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

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

這就實現(xiàn)了頁面跳轉的功能點,接下來實現(xiàn)獲取回復的評論的信息。

獲取回復的評論信息

有人會說獲取回復的評論信息,這不簡單么?加個 click 事件不就行了。還記得上一篇文章咱們是如何實現(xiàn)梯形展示評論的么?咱們是通過遞歸來實現(xiàn)的,怎么添加 click 事件讓一個不知道嵌了多少層的組件能夠把評論信息傳給父組件?首先不具體想怎么實現(xiàn),我們這個思路是不是對的:把子組件的信息傳給父組件?答案是肯定的,我們就是要把不管嵌了多少層的子組件的信息傳給 comment.component.ts 這個評論模塊的主組件。
Angular 提供了 @Output 來實現(xiàn)子組件向父組件傳遞信息,我們在 comment-view.component.ts 模塊中添加 @Output 向每個調用它的父組件傳信息,我們是嵌套的,這樣一層一層傳出來,直到傳給 comment-component.ts 組件。我們看代碼怎么實現(xiàn)。

實現(xiàn)代碼

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[];
 // 點擊回復時返回數(shù)據(jù)
 @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

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

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 -->
<div class="container font-small">
 <div class="row">
 <div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

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

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

解釋一下代碼邏輯:

我們在 comment-view.component.ts 添加以下幾點:

  • 定義了@Output() contentEvent

  • 添加了reply(comment: Comment) 事件在點擊回復的時候觸發(fā)的,觸發(fā)的時候 contentEvent 將 comment 傳到父模塊

  • 添加 transferToParent(event) 是接受子組件傳來的 event, 并且繼續(xù)將 event 傳到父組件

在 comment.component.ts 中定義了 getReplyComment(event) 方法,該方法接收子組件傳遞來的評論信息,并將信息顯示在頁面上。大功告成。。。

效果圖

Angular如何實現(xiàn)類似博客評論的遞歸顯示

感謝各位的閱讀!關于“Angular如何實現(xiàn)類似博客評論的遞歸顯示”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI