Angular组件之星级评价组件

作者: 真的稻城 | 来源:发表于2017-09-25 12:26 被阅读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,大功告成!

    相关文章

      网友评论

      本文标题:Angular组件之星级评价组件

      本文链接:https://www.haomeiwen.com/subject/jpgrextx.html