在商品詳情頁面添加一個發(fā)表評論功能
- 需要實現(xiàn)的效果:點擊星級組件的時候可以改變星星的狀態(tài)(空心和實心),獲取當前的下標得知點擊的是第幾顆星,由于下標是從0開始,所以rating的值為下標的值加一,然后在重新調(diào)用ngOnInit(因為在ngOnInit中是通過rating的值來決定星星是否顯示)
<p>
<span *ngFor="let star of stars;let i=index" class="glyphicon glyphicon-star glyphicon-star-empty"
[class.glyphicon-star-empty]="star" (click)="clickStar(i)"
></span>
<span>{{rating}}星</span>
</p>
clickStar(index:number){
this.rating =index+1;
this.ngOnInit()
}
- 但是用于顯示的星級組件應當是不允許點擊改動,處于只讀狀態(tài),只有評論的星級組件才可以點擊,為了控制是否能夠點擊,定義一個布爾類型的屬性readonly,默認為只讀不允許點擊為true
@Input()
private readonly:boolean =true;
clickStar(index:number){
if(!this.readonly){
this.rating =index+1;
this.ngOnInit()
}
- 在商品詳情組件中定義兩個屬性newRating,newComment,用于保存最新的評價的星級(默認5星)和輸入的評論內(nèi)容
newRating:number=5;
newComment:string="";
- 構建發(fā)表評論功能,將星級組件設置為可以點擊,雙向綁定文本框的內(nèi)容獲取輸入數(shù)據(jù),綁定按鈕的點擊事件
<div>
<div><app-start [rating]="newRating" [readonly]="false"></app-start></div>
<div>
<textarea [(ngModel)]="newComment"></textarea>
</div>
<button class="btn" (click)="addComment()">發(fā)表</button>
</div>
- 編輯點擊事件,new一個評論對象,設置要傳入的數(shù)據(jù),將剛獲取的星級數(shù)據(jù)和評論數(shù)據(jù)傳入其中,將這個評論對象推送到評論數(shù)組中
addComment(){
let comment=new Comment(0,this.product.id,new Date().toISOString(),"mine",this.newRating,this.newComment);
this.comments.unshift(comment);
}
- 但是此時發(fā)表出去的星級評價與用戶選定的星級評價并不相同,因為它并不是雙向數(shù)據(jù)綁定,因此star子組件中需要一個輸出屬性@Output,將子組件變化的rating發(fā)射出去,讓父組件接收
@Output()
private ratingChange:EventEmitter<number>=new EventEmitter();
clickStar(index:number){
if(!this.readonly){
this.rating =index+1;
this.ngOnInit();
this.ratingChange.emit(this.rating)
}
}
<app-start [(rating)]="newRating" [readonly]="false"></app-start>
- 設計一個按鈕讓評論區(qū)域從隱藏狀態(tài)到出現(xiàn),將isCommentHidden默認為true,將評論區(qū)域綁定hidden為isCommentHidden
<div>
<button class="btn btn-success" (click)="isCommentHidden=!isCommentHidden">評論</button>
</div>
<div [hidden]="isCommentHidden">
- 在點擊發(fā)表評論后將文本框情況,將星級設置為默認的5星,將評論區(qū)域隱藏
addComment(){
let comment=new Comment(0,this.product.id,new Date().toISOString(),"mine",this.newRating,this.newComment);
this.comments.unshift(comment);
this.newComment=null;
this.newRating=5;
this.isCommentHidden=true
}
- 但是在設置完之后,其他樣式顯示完全和預期一樣,但是星級評價的數(shù)據(jù)變成5星,但是星星的樣式卻沒有復位,使用ngOnChanges,在star組件中調(diào)用ngOnInit,讓其在輸入屬性rating改變時改變stars數(shù)組,再次判斷星級
ngOnChanges(changes: SimpleChanges): void {
this.ngOnInit()
}
- 在發(fā)表評論評定星級后,讓商品的平均分隨之變化
當開始第一次循環(huán)是傳入的sum是右邊的值0,comment是數(shù)組中的第一個元素,在這個匿名回調(diào)中用0加上第一個評星作為返回值,也就是下一次調(diào)用回調(diào)的sum
addComment(){
let comment=new Comment(0,this.product.id,new Date().toISOString(),"mine",this.newRating,this.newComment);
this.comments.unshift(comment);
let sum =this.comments.reduce((sum,comment)=>sum + comment.rating,0);
this.product.rating=sum/this.comments.length;
this.newComment=null;
this.newRating=5;
this.isCommentHidden=true
}
- 最后使用管道格式化星級評分
<span>{{rating |number:'1.0-2'}}星</span>