继续参照上一篇中介绍的知乎文章,借鉴一些想法,又加入本身的一些想法,开始初步完成一个应用的闭环。css
一开始只是实现了很是简单的加分减分功能,这样虽然方便本身给本身记分,可是限制太少,也没有具体的目标。所以,为了作出相对完整的功能,开始细化任务及其数据结构。react
设想了一下每日任务打卡的场景,画了一些流程草图,逐步定下来了任务的相关数据:数据库
任务 id (暂时先用任务标题)
用户 id (目前是单用户,默认为 0)
标题(任务名称)
描述
类型(是任务仍是欲望)
分数(根据类型决定加分仍是减分)
天天最多使用次数
建立时间
最近更新
复制代码
目前,任务以 JSON 格式存储在一个 JS 文件中。以后会将其存入数据库中。数组
任务的相关功能:缓存
无非就是数据库的 CURD 工做。bash
数据(或者 state)要由组件来承载。如今构思到的组件是:分数显示组件、任务组件以及导航组件。antd
导航组件贯穿整个 APP,首页显示分数组件,经过导航进入任务/欲望界面,并在该界面显示相应的任务/欲望。数据结构
在第 0 篇中,由于刚写出来的乞丐乞丐版是真·SPA,因此只须要用 local state,加上 localStorage 来缓存数据以便以后读取。post
代码长这样:学习
import React, { Component } from 'react';
import './App.css';
import { Row, Button, Icon } from 'antd';
class App extends Component {
constructor(props){
super(props);
this.state = {
score: localStorage.getItem('score') ? parseInt(localStorage.getItem('score')) : 0
};
this.increase = this.increase.bind(this);
this.decrease = this.decrease.bind(this);
this.clearScore = this.clearScore.bind(this);
}
increase(){
this.setState({
score: this.state.score + 1
});
}
decrease(){
this.setState({
score: this.state.score - 1
});
console.log(this.state.score);
}
clearScore(){
this.setState({
score: 0
});
}
componentDidUpdate() {
localStorage.setItem('score', this.state.score);
}
render() {
return (
<div className="App">
<Row>
<Button className="operation" onClick={this.increase}>
<Icon type="plus" />
</Button>
</Row>
<Row>
<Button className="operation" onClick={this.decrease}>
<Icon type="minus" />
</Button>
</Row>
<div className="score">
<h2>{this.state.score}</h2>
</div>
<div className="clear">
<Button onClick={this.clearScore}>Clear</Button>
</div>
</div>
);
}
}
export default App;
复制代码
local storage 有个小坑,就是存进去的数值被转化成字符串了。所以每次读取的时候都须要转回数字。
有了页面、组件之后,更新分数的方法被绑在了 task 组件上,这样不能更新到上一级页面的分数。因此每次点击完都须要刷新页面,让任务页面组件读取本地缓存。
// ListPage 做为全部项目的容器
import React, { Component } from 'react';
import { Row, Col, Button } from 'antd';
import "./ListPage.css";
class ListPage extends Component {
constructor(props) {
super(props);
this.state = {
score: localStorage.getItem('score') ? parseInt(localStorage.getItem('score')) : 0
};
}
clearScore() {
this.setState({
score: 0
});
}
componentDidUpdate() {
localStorage.setItem('score', this.state.score);
}
render() {
const { type } = this.props.match.params;
console.log(type);
return (
<div> <Row> <div className="score-list"> <h2>{this.state.score}</h2> </div> </Row> </div>
);
}
}
export default ListPage;
复制代码
// 容器中读取 list 数据,每个数据对应一个 ListItem
import React, { Component } from 'react';
import { Card, Row, Col, Button } from 'antd';
import "./ListItem.css";
class ListItem extends Component {
constructor(props){
super(props)
this.state = {
buttonVisible: false
}
}
onClickListItem(itemInfo) {
console.log(itemInfo.name, itemInfo.type)
this.setState({
buttonVisible: !this.state.buttonVisible
})
}
changeScore(itemInfo) {
let score = parseInt(localStorage.getItem("score"))
if(itemInfo.type === "task") {
score += itemInfo.score
} else {
score -= itemInfo.score
}
localStorage.setItem("score", score)
}
render(){
const { itemInfo } = this.props
return (
<Card className="list-item" onClick={() => {this.onClickListItem(itemInfo)}}> <Row> <Col span={16} className="list-item-info"> <h3>{itemInfo.name}</h3> <p>{itemInfo.desc}</p> </Col> <Col span={8}> {itemInfo.type==="task" && <div className="item-score">+{itemInfo.score}</div>} {itemInfo.type==="desire" && <div className="item-score-desire">-{itemInfo.score}</div>} </Col> </Row> {this.state.buttonVisible && (<Row> <Button onClick={() => {this.changeScore(itemInfo)}}>打卡</Button> </Row>)} </Card>
)
}
}
export default ListItem;
复制代码
这时就须要一个全局的状态管理。 (是否有更简单暴力的方法呢?好比自动刷新页面?或许能够,可是这会影响使用体验,且不利于之后增长其余功能,迟早会形成混乱。)
曾经使用过 Redux,刚入门的时候感受到很是痛苦。又要 action,action types,reducer,store。虽然最后大体搞明白了,可是仍是留下了一些坑,还有一个更新数据会赋值为对象的一个奇怪 bug。因此,接下来的文章中,我会边学习 MobX 边总结 Redux 的思想,将二者进行对比。