angular4学习笔记(第六章 组件通信篇)

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;
    
      }
    
    }
    

5.界面展示

猜你喜欢

转载自blog.csdn.net/cxzlp12345/article/details/87341578
今日推荐