over 2 years ago

先準備好CSS圖片
rateit.css

.rateit-bg-star{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxhYWdfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHdpZHRoPSIxNnB4IiBoZWlnaHQ9IjE2cHgiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTYgMTYiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8zXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIwLjIwNyIgeTE9IjgiIHgyPSIxNS43OTIiIHkyPSI4Ij4NCgk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojQ0NDQ0NDIi8+DQoJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0U2RTZFNiIvPg0KPC9saW5lYXJHcmFkaWVudD4NCjxwYXRoIGZpbGw9InVybCgjU1ZHSURfM18pIiBkPSJNOC4zNjcsMC44MTRsMS45ODQsNC42OTFsNS4wNzQsMC40MzRjMC4zNTIsMC4wMzEsMC40OTYsMC40NzMsMC4yMjcsMC43MDNsLTMuODQ4LDMuMzM2bDEuMTUyLDQuOTYxDQoJYzAuMDgyLDAuMzQ0LTAuMjkzLDAuNjE3LTAuNTk0LDAuNDM0TDgsMTIuNzRsLTQuMzYzLDIuNjMzYy0wLjMwMSwwLjE4LTAuNjc2LTAuMDktMC41OTQtMC40MzRsMS4xNTItNC45NjFMMC4zNDQsNi42NDINCglDMC4wNzgsNi40MDgsMC4yMjMsNS45NywwLjU3NCw1LjkzOWw1LjA3NC0wLjQzNGwxLjk4NS00LjY5MUM3Ljc2OSwwLjQ4Niw4LjIzLDAuNDg2LDguMzY3LDAuODE0TDguMzY3LDAuODE0eiBNOC4zNjcsMC44MTQiLz4NCjwvc3ZnPg0K)}

.rateit-selected{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxhYWdfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHdpZHRoPSIxNnB4IiBoZWlnaHQ9IjE2cHgiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTYgMTYiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8zXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIwLjIwNyIgeTE9IjgiIHgyPSIxNS43OTIiIHkyPSI4Ij4NCgk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojRkJCMDNCIi8+DQoJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0ZGOTQyRCIvPg0KPC9saW5lYXJHcmFkaWVudD4NCjxwYXRoIGZpbGw9InVybCgjU1ZHSURfM18pIiBkPSJNOC4zNjcsMC44MTRsMS45ODQsNC42OTFsNS4wNzQsMC40MzRjMC4zNTIsMC4wMzEsMC40OTYsMC40NzMsMC4yMjcsMC43MDNsLTMuODQ4LDMuMzM2bDEuMTUyLDQuOTYxDQoJYzAuMDgyLDAuMzQ0LTAuMjkzLDAuNjE3LTAuNTk0LDAuNDM0TDgsMTIuNzRsLTQuMzYzLDIuNjMzYy0wLjMwMSwwLjE4LTAuNjc2LTAuMDktMC41OTQtMC40MzRsMS4xNTItNC45NjFMMC4zNDQsNi42NDINCglDMC4wNzgsNi40MDgsMC4yMjMsNS45NywwLjU3NCw1LjkzOWw1LjA3NC0wLjQzNGwxLjk4NS00LjY5MUM3Ljc2OSwwLjQ4Niw4LjIzLDAuNDg2LDguMzY3LDAuODE0TDguMzY3LDAuODE0eiBNOC4zNjcsMC44MTQiLz4NCjwvc3ZnPg0K)}
[class^=rateit-] {
  width: 16px;
  height: 16px
}

RateitComponent.js

import React, { Component } from 'react';
import './rateit.css';

class Rateit extends Component {
  constructor(props) {
    super(props);
    this.state = { selectedValue: this.props.selectedValue };
  }
  _processRateit(selectedValue) {
    for(let i = 1; i <= this.props.length; i++) {
      (selectedValue >= i) ?
        this.refs[i].classList.add("rateit-selected"):
        this.refs[i].classList.remove("rateit-selected");
    }
  }
  _onClick(selectedValue) {
    const setValue = (this.state.selectedValue === selectedValue) ? 0 : selectedValue;
    this._processRateit(setValue);
    this.setState({ selectedValue : setValue });
  }
  getSelectedValue() {
    return this.state.selectedValue;
  }
  render() {

    const {length, order} = this.props;

    let stars = [];

    for(let i = 1; i <= length; i++) {
      let className = (this.state.selectedValue >= i) ? 
                                    'rateit-bg-star rateit-selected':'rateit-bg-star';
      stars.push(
          <div key={i} className={className} ref={i}
          onMouseOver={this._processRateit.bind(this, i)}
          onMouseOut={this._processRateit.bind(this, this.state.selectedValue)}
          onClick={this._onClick.bind(this, i)}
          />
        );
    }

    const containerStyle = { 'display': 'flex',
                             'justifyContent': (order === 'ASC') ? 'flex-start' : 'flex-end',
                             'flexDirection':  (order === 'ASC') ? 'row'        : 'row-reverse' };
    return (
      <div style={containerStyle}>
        {stars}
      </div>
    )
  }
}
// 配置預設 props 
Rateit.defaultProps = {
  order: 'ASC', // 遞增或遞減
  length: 5,    // 星星長度
  selectedValue: 0 // 預設選取值
}
// 配置 propTypes 
Rateit.propTypes  = {
  order: React.PropTypes.oneOf(['ASC', 'DESC']),
  size:React.PropTypes.number,
  length: React.PropTypes.number,
  selectedValue: React.PropTypes.number
}

export default Rateit;

使用方式

import React, { Component } from 'react';
import Rateit from './Components/RateitComponent';

class App extends Component {
  _Send(e) {
    console.log(`RateitOne : ${this.refs.RateitOne.getSelectedValue()}`);
    console.log(`RateitTwo : ${this.refs.RateitTwo.getSelectedValue()}`);
  }
  render() {
    return (
      <div className="App">
        <Rateit ref="RateitOne" length={10} />
        <Rateit ref="RateitTwo" order={'DESC'}/>
        <button onClick={this._Send.bind(this)}>Send</button>
      </div>
    );
  }
}

export default App;

效果
RateitComponent

← 於 React.render 使用 立即呼叫函式(IIFE) 處理複雜的判斷式 使用 nvm 管理 Node 版本 →
 
comments powered by Disqus