Angular入门与实战Web前端之路让前端飞

Angular组件之星级评价组件

2017-09-25  本文已影响451人  真的稻城

首先上实现的步骤:

  1. 如何显示一颗星星
  2. 如何显示一个空心的星星
  3. 如何显示定义数量的星星
  4. 如何让定义数量的星星有的空心、有的实心
  5. 如何把评分数值传递到组件中,根据评分显示个数
  6. 让传递进来的值控制最大的可显示的星星数
  7. 添加点击事件来操作评分,并改变对应星星个数
  8. 当可点击之后,我们通过变量来控制是否能点击。
  9. 把点击的星星发射出去。

第一步(安装环境)

  1. cnpm install -g @angular/cli (全局安装angular-cli)
  2. ng new my-star (new 一个新项目 )
  3. cd my-star (进入刚才我们new的新项目)
  4. ng serve --open (在浏览器中打开)

第二步(引入Bootstrap样式)

  1. cnpm install bootstrap --save
  2. 在,angular-cli.json中的style中加入"../node_modules/_bootstrap@3.3.7@bootstrap/dist/css/bootstrap.min.css",(如果你是用npm下载的,那么bootstrap的包名可能会不一样,请在node_modules文件下查看)
  3. OK,这样就可以使用bootstrap的样式了.

第三步(修改app文件夹下的app.component.html文件代码)

<div style="text-align:center">
  <h1>
    <app-my-star></app-my-star>
  </h1>
  <h2>
    <span>星</span>
  </h2>
  <img width="300" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
</div>

第四步(修改my-star文件夹下的my-star.component.html文件代码)

<span>
  <span class="glyphicon glyphicon-star"></span>
</span>
//glyphicon-star是bootstrap字体样式,如果想要空心可以使用glyphicon-star-empty

第五步(修改my-star文件夹下的my-star.component.html和my-star-component.ts文件代码,实现多颗星星)

//my-star-component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-my-star',
  templateUrl: './my-star.component.html',
  styleUrls: ['./my-star.component.css']
})
export class MyStarComponent implements OnInit {

  public stars = [];

  constructor() { }

  ngOnInit() {
    this.stras = [true,true,false,true,true] 
  }
}
//my-star-component.html
<span>
  <span *ngFor="let star of stars" class="glyphicon glyphicon-star" ></span>
</span>
//通过*ngFor循环实现多颗星星

第六步(通过属性绑定class,实现空心的星星和实心的星星)

//my-star.component.html
<span>
  <span *ngFor="let star of stars" class="glyphicon glyphicon-star" [class.glyphicon-star-empty]="!star"></span>
</span>

第七步(现在我们的星星个数是我们的stars数组写死的,那么怎么把它变成可由我们自己控制的)

//在父组件中定义三个属性,rating是实心的星星数,max是最大的星星数量,readonly是是否可点击,为true时不可点击。
//app.component.html
<div style="text-align:center">
  <h1>
    <app-my-star [(rating)]="rating" [max]="max" [readonly]="readonly"></app-my-star>
  </h1>
  <h2>
    <span>{{ rating | number:'1.0-1'}}星</span>
  </h2>
  <img width="300" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
</div>
//app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  public max: number = 10;
  public rating: number = 0;
  public readonly: boolean = false;
}

//在my-star.component.ts中接收
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-my-star',
  templateUrl: './my-star.component.html',
  styleUrls: ['./my-star.component.css']
})
export class MyStarComponent implements OnInit {

  @Input()
  public rating: number;

  @Input()
  public max: number;

  @Input()
  public readonly: boolean;

  public stars = [];

  constructor() { }

  ngOnInit() {
    this.stars = [];
    for (let i = 0; i < this.max; i++) {
      this.stars.push(i < this.rating)  //rating是实心星星的个数,当rating的数值小于i的时候,往stars数组里push的就是false,星星为空心。
    }
  }
  
}

第八步(让星星实现可点击功能)

//my-star-component.html
<span>
  <span *ngFor="let star of stars; let i = index;" class="glyphicon glyphicon-star" [class.glyphicon-star-empty]="!star" (click)="onClick(i)"></span>
</span> //i 是ngFor循环的下标,通过事件绑定讲点击的是第几颗星星传入
//在my-star.component.ts中接收
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-my-star',
  templateUrl: './my-star.component.html',
  styleUrls: ['./my-star.component.css']
})
export class MyStarComponent implements OnInit {

  @Input()
  public rating: number;

  @Output()
  ratingChange: EventEmitter<number> = new EventEmitter();

  @Input()
  public max: number;

  @Input()
  public readonly: boolean;

  public stars = [];

  constructor() { }

  ngOnInit() {
    //重新清空数组
    this.stars = [];
    for (let i = 0; i < this.max; i++) {
      this.stars.push(i < this.rating)
    }
  }

  onClick(rate: number) {
    //如果readonly不为true时,
    if( !this.readonly ){
      //因为数组是从0开始,星星的个数不可能是0个,所以rate + 1
      this.rating = rate + 1; 
      this.ngOnInit();
    }
  }

第九步(根据点击,实时显示有多少颗星星)

//app.component.html
<div style="text-align:center">
  <h1>
    <app-my-star [(rating)]="rating" [max]="max" [readonly]="readonly"></app-my-star>
  </h1>
  <h2>
    <span>{{ rating | number:'1.0-1'}}星</span>
  </h2>
  <img width="300" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAyNTAgMjUwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyNTAgMjUwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDojREQwMDMxO30NCgkuc3Qxe2ZpbGw6I0MzMDAyRjt9DQoJLnN0MntmaWxsOiNGRkZGRkY7fQ0KPC9zdHlsZT4NCjxnPg0KCTxwb2x5Z29uIGNsYXNzPSJzdDAiIHBvaW50cz0iMTI1LDMwIDEyNSwzMCAxMjUsMzAgMzEuOSw2My4yIDQ2LjEsMTg2LjMgMTI1LDIzMCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAJIi8+DQoJPHBvbHlnb24gY2xhc3M9InN0MSIgcG9pbnRzPSIxMjUsMzAgMTI1LDUyLjIgMTI1LDUyLjEgMTI1LDE1My40IDEyNSwxNTMuNCAxMjUsMjMwIDEyNSwyMzAgMjAzLjksMTg2LjMgMjE4LjEsNjMuMiAxMjUsMzAgCSIvPg0KCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMjUsNTIuMUw2Ni44LDE4Mi42aDBoMjEuN2gwbDExLjctMjkuMmg0OS40bDExLjcsMjkuMmgwaDIxLjdoMEwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMUwxMjUsNTIuMQ0KCQlMMTI1LDUyLjF6IE0xNDIsMTM1LjRIMTA4bDE3LTQwLjlMMTQyLDEzNS40eiIvPg0KPC9nPg0KPC9zdmc+DQo=">
</div> //通过数据双向绑定在span标签中绑定rating。

//my-star.component.ts
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-my-star',
  templateUrl: './my-star.component.html',
  styleUrls: ['./my-star.component.css']
})
export class MyStarComponent implements OnInit {

  @Input()
  public rating: number;

  @Output()
  ratingChange: EventEmitter<number> = new EventEmitter(); 

  @Input()
  public max: number;

  @Input()
  public readonly: boolean;

  public stars = [];

  constructor() { }

  ngOnInit() {
    this.stars = [];
    for (let i = 0; i < this.max; i++) {
      this.stars.push(i < this.rating)
    }
  }

  onClick(rate: number) {
    if( !this.readonly ){
      //因为数组是从0开始,
      this.rating = rate + 1; 
      this.ngOnInit();
      this.ratingChange.emit(this.rating);
    }
  }

}
// 通过@Output,声明一个输出口属性。在通过emit用来发射值

OK,大功告成!

上一篇下一篇

猜你喜欢

热点阅读