## 第十八步:Stats组件
我们最后一个组件非常简单,仅仅是一个包含一般统计的表格,比如角色总数,按种族、性别、总投票等等统计出来的数据。这些代码甚至都无需解释,因为它们很简单。
### Component
在app/components新建文件*Stats.js*:
~~~
import React from 'react';
import StatsStore from '../stores/StatsStore'
import StatsActions from '../actions/StatsActions';
class Stats extends React.Component {
constructor(props) {
super(props);
this.state = StatsStore.getState();
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
StatsStore.listen(this.onChange);
StatsActions.getStats();
}
componentWillUnmount() {
StatsStore.unlisten(this.onChange);
}
onChange(state) {
this.setState(state);
}
render() {
return (
<div className='container'>
<div className='panel panel-default'>
<table className='table table-striped'>
<thead>
<tr>
<th colSpan='2'>Stats</th>
</tr>
</thead>
<tbody>
<tr>
<td>Leading race in Top 100</td>
<td>{this.state.leadingRace.race} with {this.state.leadingRace.count} characters</td>
</tr>
<tr>
<td>Leading bloodline in Top 100</td>
<td>{this.state.leadingBloodline.bloodline} with {this.state.leadingBloodline.count} characters
</td>
</tr>
<tr>
<td>Amarr Characters</td>
<td>{this.state.amarrCount}</td>
</tr>
<tr>
<td>Caldari Characters</td>
<td>{this.state.caldariCount}</td>
</tr>
<tr>
<td>Gallente Characters</td>
<td>{this.state.gallenteCount}</td>
</tr>
<tr>
<td>Minmatar Characters</td>
<td>{this.state.minmatarCount}</td>
</tr>
<tr>
<td>Total votes cast</td>
<td>{this.state.totalVotes}</td>
</tr>
<tr>
<td>Female characters</td>
<td>{this.state.femaleCount}</td>
</tr>
<tr>
<td>Male characters</td>
<td>{this.state.maleCount}</td>
</tr>
<tr>
<td>Total number of characters</td>
<td>{this.state.totalCount}</td>
</tr>
</tbody>
</table>
</div>
</div>
);
}
}
export default Stats;
~~~
### Actions
在app/actions目录新建*Stats.js*:
~~~
import alt from '../alt';
class StatsActions {
constructor() {
this.generateActions(
'getStatsSuccess',
'getStatsFail'
);
}
getStats() {
$.ajax({ url: '/api/stats' })
.done((data) => {
this.actions.getStatsSuccess(data);
})
.fail((jqXhr) => {
this.actions.getStatsFail(jqXhr);
});
}
}
export default alt.createActions(StatsActions);
~~~
### Store
在app/store目录新建*Stats.js*:
~~~
import {assign} from 'underscore';
import alt from '../alt';
import StatsActions from '../actions/StatsActions';
class StatsStore {
constructor() {
this.bindActions(StatsActions);
this.leadingRace = { race: 'Unknown', count: 0 };
this.leadingBloodline = { bloodline: 'Unknown', count: 0 };
this.amarrCount = 0;
this.caldariCount = 0;
this.gallenteCount = 0;
this.minmatarCount = 0;
this.totalVotes = 0;
this.femaleCount = 0;
this.maleCount = 0;
this.totalCount = 0;
}
onGetStatsSuccess(data) {
assign(this, data);
}
onGetStatsFail(jqXhr) {
toastr.error(jqXhr.responseJSON.message);
}
}
export default alt.createStore(StatsStore);
~~~
打开routes.js并添加新路由`/stats`。我们必须将它放在`:category`路由之前,这样它会被优先执行。
~~~
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';
import Stats from './components/Stats';
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='/stats' handler={Stats} />
<Route path=':category' handler={CharacterList}>
<Route path=':race' handler={CharacterList}>
<Route path=':bloodline' handler={CharacterList} />
</Route>
</Route>
</Route>
);
~~~
刷新浏览器,你应该看到如下的新Stats组件:
![](https://box.kancloud.cn/2015-09-14_55f6449fd55f8.jpg)
- 前言
- 概述
- 第一步:新建Express项目
- 第二步:构建系统
- 第三步:项目结构
- 第四步: ES6速成教程
- 第五步: React速成教程
- 第六步:Flux架构速成教程
- 第七步:React路由(客户端)
- 第八步:React路由(服务端)
- 第九步:Footer和Navbar组件
- 第十步:Socke.IO – 实时用户数
- 第十一步:添加Character的组件
- 第十二步:数据库模式
- 第十三步:Express API 路由(1/2)
- 第十五步:Home组件
- 第十四步:Express API 路由(2/2)
- 第十六步:角色(资料)组件
- 第十七步:Top 100 组件
- 第十八步:Stats组件
- 第十九步:部署
- 第二十步: 附加资源
- 总结