1.Input和Output
- 用于父组件与子组件之间(数据)通信
- input的用法
- 创建父组件与子组件(ng g c parent , ng g c child)
- 子组件界面(父组件与子组件的通信)
- 子组件使用输入属性Input,从父组件传入两个变量(学生姓名与学生学号)
- 父组件界面,添加两个输入框,向子组件传递信息
- Output的用法(子组件与父组件的通信)
- 创建分数类,使用Output向父组件发送分数
- 在父组件中声明变量与处理接收参数
- 进行通信(名称也可以像Input一样自定义)
- 兄弟组件间相互通信,使用中间人模式,通过父组件通信
- 把上个例子中的成绩,单独放到另一个子组件中
- 通过父组件将子组件发射的成绩传递到子组件1中
- 对于非父子组件和兄弟组件,可通过创建一个服务来作为中间人(后续补充)
2.ViewChild
- 父组件使用子组件的方法
- 在子组件中创建sayHi的方法
- 在父组件中引用viewChild,创建模板本地变量
3.ng-content
-
在某些情况下,需要动态改变模板的内容,可以用路由,但路由是一个相对比较麻烦的东西,而我要实现的功能没有那么复杂,没有什么业务逻辑,也不需要重用。这个时候可以用ng-content投影将父组件中任意片段投影到子组件中。
-
在父组件的子组件标签内放置需要投影的内容
-
在子组件需要放置内容的地方放置ng-content标签
4.更新在线竞拍
- 添加一个评价功能
- 修改星级组件,添加一个点击事件
<!-- 根据ngclass和ngstyle来判断是否为实心星星 --> <!-- 添加click点击事件,用于动态修改星级组件评分 --> <span *ngFor="let star of stars,let i =index" class="glyphicon glyphicon-star" (click)="clickStar(i)" [ngClass]="{'glyphicon-star-empty':!star}" [ngStyle]="{'color': !star?'yellowgreen':'#ddd'}"> </span>
- 点击星级组件,修改评分
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-stars', templateUrl: './stars.component.html', styleUrls: ['./stars.component.css'] }) export class StarsComponent implements OnInit { //加一个input装饰器:星级评价组件StarsComponent的rating属性应该由它的父组件传递给它 //定义一个属性:用来接收产品组件传给它的星级评价数值,默认值是0 @Input() private rating: number = 0; // 定义一个只读属性,用来判断星级组件是否为只读 @Input() public readonly: boolean = true; // 添加一个输出属性,用于双向绑定星级组件数据 @Output() ratingChange: EventEmitter<number> = new EventEmitter(); //定义一个Boolean类型的数组:装5颗星 public stars: boolean[]; constructor() { } ngOnInit() { this.stars = []; for (var i = 1; i <= 5; i++) { this.stars.push(i > this.rating); } } // 星级组件点击事件 clickStar(newRating) { // 判断是否为只读 if (!this.readonly) { this.rating = newRating + 1; this.ngOnInit(); // 发射数据,动态修改星级组件星级数 this.ratingChange.emit(this.rating) } } }
- 在商品详情页添加一个评分功能
<div class="row"> <img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3671643272,946673945&fm=26&gp=0.jpg" alt=""> </div> <hr> <!-- 商品详情 --> <div class="thumbnail"> <div class="caption"> <span class="pull-right text-info">¥{{productinfo.price}}</span> <p>{{productinfo.name}}</p> <p> <app-stars [rating]="productinfo.rating"></app-stars> <span> {{productinfo.rating | number: '1.1-1'}} 星</span> </p> </div> </div> <hr> <!-- 相关评论 --> <div class="panel panel-default" *ngFor="let comments of commentinfo"> <div class="panel-heading clearfix"> <div class="pull-left"> <h4> 用户:{{comments.user}} </h4> </div> <div class="pull-right"> <h4> <app-stars [rating]="comments.rating"></app-stars> <span> {{comments.rating | number: '1.1-1'}} 星</span> </h4> </div> </div> <div class="panel-body"> <p>评分内容:{{comments.content}}</p> <span class="pull-right">评分时间:{{comments.time}}</span> </div> </div> <div class="panel panel-default" *ngIf="!hasComment"> <div class="panel-heading"> <h3>暂无评论</h3> </div> <div class="panel-body"> 该商品暂无相关评论信息 </div> </div> <!-- 评价功能 --> <div class="panel panel-default"> <div class="panel-heading"> <!-- 发表评论按钮 --> <button class="btn btn-success" (click)="isAddComment=!isAddComment">发表评论</button> </div> <div class="panel-body" *ngIf="isAddComment"> <!-- 双向绑定星级组件,设置星级组件为可编辑 --> <app-stars [(rating)]="newRating" [readonly]='false'></app-stars> <!-- 使用数字管道更改评分格式 --> <span> {{newRating | number: '1.1-1'}} 星</span> <hr> <!-- 评论内容 --> <textarea [(ngModel)]="newComment" name="comment-content" id="comment-content" class="form-control" rows="6" placeholder="请输入评论内容(300字以内)"></textarea> </div> <div class="panel-footer clearfix" *ngIf="isAddComment"> <!-- 提交按钮 --> <button class="btn btn-default pull-right" *ngIf="newComment" (click)="addComment()">提交</button> <button class="btn btn-default pull-right" *ngIf="!newComment" disabled>提交</button> </div> </div>
- 在商品服务中添加一个添加评价的方法
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; import { ProductService, Products, Comment } from 'src/shared/product.service'; @Component({ selector: 'app-detialproduct', templateUrl: './detialproduct.component.html', styleUrls: ['./detialproduct.component.css'] }) export class DetialproductComponent implements OnInit { // 声明变量接收参数 private productName: string; private productId: number; private productinfo: Products; private commentinfo: Comment[]; private hasComment: boolean; // 隐藏于显示评论输入文本框 private isAddComment: boolean = false; // 添加评价默认分数 private newRating: number = 5; // 添加评价内容 private newComment: string; // 注入商品服务 constructor(private routerinfo: ActivatedRoute, private _ProductService: ProductService) { } ngOnInit() { // 使用参数订阅方式获取数据 // 以为此处确定不会自身路由到自身路由,所以选择使用参数快照方式 // this.routerinfo.params.subscribe((params : Params) => this.productName = params['name'] ); // this.routerinfo.params.subscribe((params : Params) => this.productId = params['id'] ); // 使用参数快照方式获取数据 this.productName = this.routerinfo.snapshot.params['name']; this.productId = this.routerinfo.snapshot.params['id']; // 使用商品服务的getProductById()方法获取商品详情信息 this.productinfo = this._ProductService.getProductById(this.productId); // 使用商品服务的getCommentById()方法获取商品相关评论信息 this.commentinfo = this._ProductService.getCommentById(this.productId); // 判断是否有评论信息 if (this.commentinfo.length < 1) { this.hasComment = false; } else { this.hasComment = true; } } // 提交评价事件 addComment() { // 添加评价信息 var addComment = new Comment(Date.parse('2019-01-18 14:25:15'), this.productId, '2019-01-18 14:25:15', 'username', this.newRating, this.newComment); // 调用添加评论服务 this._ProductService.addComments(addComment); // 更新评论信息 this.commentinfo = this._ProductService.getCommentById(this.productId); // 总评价分数 var sumRating = 0; for (var i = 0; i < this.commentinfo.length; i++) { sumRating = sumRating + this.commentinfo[i].rating; } // 平均评分 this.productinfo.rating = sumRating / this.commentinfo.length; // 重置评价输入信息 this.newRating = 5; this.newComment = null; this.isAddComment = false; } }