第十七步:Top 100 組件

2021-10-23 14:32 更新

第十七步:Top 100 組件

這個組件使用Bootstrap的Media控件作為主要的界面,下面是它看起來的樣子:

Component

在app/components目錄新建文件CharacterList.js

import React from 'react';
import {Link} from 'react-router';
import {isEqual} from 'underscore';
import CharacterListStore from '../stores/CharacterListStore';
import CharacterListActions from '../actions/CharacterListActions';

class CharacterList extends React.Component {
  constructor(props) {
    super(props);
    this.state = CharacterListStore.getState();
    this.onChange = this.onChange.bind(this);
  }

  componentDidMount() {
    CharacterListStore.listen(this.onChange);
    CharacterListActions.getCharacters(this.props.params);
  }

  componentWillUnmount() {
    CharacterListStore.unlisten(this.onChange);
  }

  componentDidUpdate(prevProps) {
    if (!isEqual(prevProps.params, this.props.params)) {
      CharacterListActions.getCharacters(this.props.params);
    }
  }

  onChange(state) {
    this.setState(state);
  }

  render() {
    let charactersList = this.state.characters.map((character, index) => {
      return (
        <div key={character.characterId} className='list-group-item animated fadeIn'>
          <div className='media'>
            <span className='position pull-left'>{index + 1}</span>
            <div className='pull-left thumb-lg'>
              <Link to={'/characters/' + character.characterId}>
                <img className='media-object' src={'http://image.eveonline.com/Character/' + character.characterId + '_128.jpg'} />
              </Link>
            </div>
            <div className='media-body'>
              <h4 className='media-heading'>
                <Link to={'/characters/' + character.characterId}>{character.name}</Link>
              </h4>
              <small>Race: <strong>{character.race}</strong></small>
              <br />
              <small>Bloodline: <strong>{character.bloodline}</strong></small>
              <br />
              <small>Wins: <strong>{character.wins}</strong> Losses: <strong>{character.losses}</strong></small>
            </div>
          </div>
        </div>
      );
    });

    return (
      <div className='container'>
        <div className='list-group'>
          {charactersList}
        </div>
      </div>
    );
  }
}

CharacterList.contextTypes = {
  router: React.PropTypes.func.isRequired
};

export default CharacterList;

鑒于角色數(shù)組已經(jīng)按照勝率進行了排序,我們可以使用index + 1(從1到100)來作為數(shù)組下標(biāo)直接輸出角色。

Actions

在app/actions目錄新建CharacterListActions.js

import alt from '../alt';

class CharacterListActions {
  constructor() {
    this.generateActions(
      'getCharactersSuccess',
      'getCharactersFail'
    );
  }

  getCharacters(payload) {
    let url = '/api/characters/top';
    let params = {
      race: payload.race,
      bloodline: payload.bloodline
    };

    if (payload.category === 'female') {
      params.gender = 'female';
    } else if (payload.category === 'male') {
      params.gender = 'male';
    }

    if (payload.category === 'shame') {
      url = '/api/characters/shame';
    }

    $.ajax({ url: url, data: params })
      .done((data) => {
        this.actions.getCharactersSuccess(data);
      })
      .fail((jqXhr) => {
        this.actions.getCharactersFail(jqXhr);
      });
  }
}

export default alt.createActions(CharacterListActions);

這里的payload包含React Router參數(shù),這些參數(shù)我們將在routes.js中指定。

<Route path=':category' handler={CharacterList}>
  <Route path=':race' handler={CharacterList}>
    <Route path=':bloodline' handler={CharacterList} />
  </Route>
</Route>

比如,如果我們訪問http://localhost:3000/female/gallente/intaki ,則payload對象將包括下列數(shù)據(jù):

{
  category: 'female',
  race: 'gallente',
  bloodline: 'intaki'
}

Store

在app/store目錄下新建文件CharacterListStore.js

import alt from '../alt';
import CharacterListActions from '../actions/CharacterListActions';

class CharacterListStore {
  constructor() {
    this.bindActions(CharacterListActions);
    this.characters = [];
  }

  onGetCharactersSuccess(data) {
    this.characters = data;
  }

  onGetCharactersFail(jqXhr) {
    toastr.error(jqXhr.responseJSON.message);
  }
}

export default alt.createStore(CharacterListStore);/pre>
打開route.js并添加下列路由。所有內(nèi)嵌路由都使用動態(tài)區(qū)段,所以不用重復(fù)輸入。確保它們在路由的最后面,否則:category將會覆蓋其它路由如/stats、/add和/shame。不要忘了導(dǎo)入CharacterList組件:
import React from 'react';
import {Route} from 'react-router';
import App from './components/App';
import Home from './components/Home';
import AddCharacter from './components/AddCharacter';
import Character from './components/Character';
import CharacterList from './components/CharacterList';

export default (
  <Route handler={App}>
    <Route path='/' handler={Home} />
    <Route path='/add' handler={AddCharacter} />
    <Route path='/characters/:id' handler={Character} />
    <Route path='/shame' handler={CharacterList} />
    <Route path=':category' handler={CharacterList}>
      <Route path=':race' handler={CharacterList}>
        <Route path=':bloodline' handler={CharacterList} />
      </Route>
    </Route>
  </Route>
);

下面是所有動態(tài)區(qū)段可以取的值:

  • :category — male, female, top.
  • :race — caldari, gallente, minmatar, amarr.
  • :bloodline — civire, deteis, achura, intaki, gallente, jin-mei, amarr, ni-kunni, khanid, brutor, sebiestor, vherokior.

可以看到,如果我們使用硬編碼的話,將如此多的路由包含進去將使route.js變得很長很長。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號