javascript - React - 如果分数发生变化,则按最高分数对记分牌上的玩家进行排序

标签 javascript reactjs sorting components

我构建了一个 React 应用程序,它是一个记分板。您可以使用右侧的 + 和 - 符号在玩家的得分中添加和删除分数。目前,玩家按 ID 排序。我想找出一种方法根据玩家当前的得分对他们进行排序。

例如,如果一名玩家获得的分数高于其上方的另一名玩家,则该玩家将上升到他们排名所在的行。我制作了一个 Codepen 来展示我的项目。如果有人知道如何在运行 onScoreChange 函数后对玩家进行排序,我将非常感激!

CodePen

<div id="container"></div>
body {
  background: #d5d5d5;
  font-family: arial;
  color: #FAFAFA;
  text-transform: uppercase;
}

.scoreboard {
  background: #333;
  width: 700px;
  margin: 70px auto;
  box-shadow: 0 4px 0px #333;
  border-radius: 15px;

}

.header {
  padding: 5px 10px;
  text-align: center;
  display: flex;
  align-items: center;
  background-color: #222;
  border-radius: 15px 15px 0 0;
  border-bottom: solid 2px #444;
}

.header h1 {
  flex-grow: 1;
  font-size: 1.5em;
  letter-spacing: 3px;
  font-weight: normal;
}

.player {
  display: flex;
  font-size: 1.2em;
  border-bottom: solid 2px #444;
  letter-spacing: 2px;
}

  .remove-player {
    visibility: hidden;
    margin-right: 10px;
    color: #e57373;
    cursor: pointer;
  }

  .player-name:hover .remove-player {
    visibility: visible;
  }

  .player-name {
    flex-grow: 1;
    padding: 20px 10px 10px 10px;
  }

  .player-score {
    width: 190px;
    background: blue;
  }

  .counter {
    display: flex;
  }

  .counter-action {
    border: none;
    font-weight: bold;
    color: #FAFAFA;
    display: block;
    padding: 20px 20px;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }

  .counter-action.increment {
    background: #66BB6A;
  }

  .counter-action.increment:hover {
    background: #549d59;
    cursor: pointer;
  }

  .counter-action.decrement {
    background: #ef5350;
  }

  .counter-action.decrement:hover {
    background: #c44442;
    cursor: pointer;
  }

  .counter-score {
    flex-grow: 1;
    background: #2b2b2b;
    color: #FAFAFA;
    text-align: center;
    font-family: monospace;
    padding: 10px;
    font-size: 2em;
  }


.add-player-form form {
  display: flex;
  background-color: #222;
  border-radius: 0 0 20px 20px
}

  .add-player-form input[type=text] {
    flex-grow: 1;
    border-width: 0 0 1px 0;
    margin: 15px 10px 15px 15px;
    padding: 10px;
    border-radius: 5px;
    background-color: #333;
    border-style: none;
    text-shadow: none;
    text-transform: uppercase;
    color: #999;
    letter-spacing: 2px;
    outline: none;
  }

  .add-player-form input[type=text]::-webkit-input-placeholder{
    color: #666;
    letter-spacing: 2px;
  }

  .add-player-form input[type=text]:focus{
    background-color: #444;
  }

  .add-player-form input[type=submit] {
    display: block;
    font-size: .6em;
    margin: 15px 15px 15px 0;
    padding: 10px;
    background-color: #333;
    border-radius: 5px;
    border: none;
    color: #999;
    letter-spacing: 2px;
    font-weight: bold;
    text-shadow: none;
    text-transform: uppercase;
  }

  .add-player-form input[type=submit]:hover{
    background: #4b71b5;
    color: #fafafa;
    cursor: pointer;
  }

var PLAYERS = [
  {
    name: "Mary Miller",
    score: 22,
    id: 1,
  },
  {
    name: "Ellie Grace",
    score: 20,
    id: 2,
  },
  {
    name: "Ben Pine",
    score: 18,
    id: 3,
  },
  {
    name: "Rachel Slater",
    score: 17,
    id: 4,
  },
  {
    name: "Lisette Ven",
    score: 10,
    id: 5,
  },
];

var nextId = 6;

var AddPlayerForm = React.createClass({
  propTypes: {
    onAdd: React.PropTypes.func.isRequired,
  },

  getInitialState: function() {
    return {
      name: "",
    };
  },

  onNameChange: function(e) {
    this.setState({name: e.target.value});
  },

  onSubmit: function(e) {
    e.preventDefault();

    this.props.onAdd(this.state.name);
    this.setState({name: ""});
  },


  render: function() {
    return (
      <div className="add-player-form">
        <form onSubmit={this.onSubmit}>
          <input type="text" value={this.state.name} onChange={this.onNameChange} />
          <input type="submit" value="Add Player" />
        </form>
      </div>
    );
  }
});

function Header(props) {
  return (
    <div className="header">
      <h1>{props.title}</h1>
    </div>
  );
}

Header.propTypes = {
  title: React.PropTypes.string.isRequired,
  players: React.PropTypes.array.isRequired,
};

function Counter(props) {
  return (
    <div className="counter">
      <button className="counter-action decrement" onClick={function() {props.onChange(-1);}} > - </button>
      <div className="counter-score"> {props.score} </div>
      <button className="counter-action increment" onClick={function() {props.onChange(1);}}> + </button>
    </div>
  );
}

Counter.propTypes = {
  score: React.PropTypes.number.isRequired,
  onChange: React.PropTypes.func.isRequired,
}

function Player(props) {
  return (
    <div className="player">
      <div className="player-name">
        <a className="remove-player" onClick={props.onRemove}>✖</a>
        {props.name}
      </div>
      <div className="player-score">
        <Counter score={props.score} onChange={props.onScoreChange} />
      </div>
    </div>
  );
}

Player.propTypes = {
  name: React.PropTypes.string.isRequired,
  score: React.PropTypes.number.isRequired,
  onScoreChange: React.PropTypes.func.isRequired,
  onRemove: React.PropTypes.func.isRequired,
};



var Application = React.createClass({
  propTypes: {
    title: React.PropTypes.string,
    initialPlayers: React.PropTypes.arrayOf(React.PropTypes.shape({
      name: React.PropTypes.string.isRequired,
      score: React.PropTypes.number.isRequired,
      id: React.PropTypes.number.isRequired,
    })).isRequired,
  },

  getDefaultProps: function() {
    return {
      title: "Foosball Scoreboard",
    }
  },

  getInitialState: function() {
    return {
      players: this.props.initialPlayers,
    };
  },

  onScoreChange: function(index, delta) {
    this.state.players[index].score += delta;
    this.setState(this.state);
  },

  onPlayerAdd: function(name) {
    this.state.players.push({
      name: name,
      score: 0,
      id: nextId,
    });
    this.setState(this.state);
    nextId += 1;
  },

  onRemovePlayer: function(index) {
    this.state.players.splice(index, 1);
    this.setState(this.state);
  },

  // reorderPlayers

  render: function() {
    return (
      <div className="scoreboard">
        <Header title={this.props.title} players={this.state.players} />

        <div className="players">
          {this.state.players.map(function(player, index) {
            return (
              <Player
                onScoreChange={function(delta) {this.onScoreChange(index ,delta)}.bind(this)}
                onRemove={function() {this.onRemovePlayer(index)}.bind(this)}
                name={player.name}
                score={player.score}
                key={player.id} />
            );
          }.bind(this))}
        </div>
        <AddPlayerForm onAdd={this.onPlayerAdd} />
      </div>
    );
  }
});



ReactDOM.render(<Application initialPlayers={PLAYERS}/>, document.getElementById('container'));

最佳答案

只需使用 Array.sort onScoreChange 函数中的函数每次分数更改时都会对数组进行排序,如下所示

onScoreChange: function(index, delta) {
    let players = [...this.state.players]

    players[index] = Object.assign({},players[index])
    // Or if you can use object spread then: players[index] = {...players[index]}
    players[index].score += delta;

    // Use Array.sort function like this
    players.sort((a,b) => b.score - a.score)
    this.setState({players});
  },

关于javascript - React - 如果分数发生变化,则按最高分数对记分牌上的玩家进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47294314/

相关文章:

javascript - JavaScript 中的虚函数是什么?

ReactJS 模态不使用 Materialize css 打开

Ruby - 为什么排序重新排序相等的元素

javascript - React 从表中删除列

javascript - 在react redux中唯一地计算某些元素

java - Java中 block 的排序日期列表

C++自动评分系统

javascript - Handsontable 中的多个编辑器

javascript - 当窗口大小调整时,优雅地自动调整 Galleria jQuery 幻灯片的大小

javascript - 避免选择的变体计算价格反射(reflect)在 Woocommerce 相关产品中