实践前需要了解redux的原理,本文是具体实现。
实现的效果:【增加待办事项,将待办事项只完成(未完成),筛选】
(1)let store=createStore(reducer);创建项目的store,需要传入的参数是reducer,reducer是我们根据项目需要自己编写的,是按照不同的操作(action)返回新的state。createStore是redux提供的方法,需要引入redux。
(2) <Provider store={store}>将store注入,把项目的组件都包含在Provider里,项目所有的组件都能够获取store(是通过context来实现的,可以看看redux的原理讲解)Provider是react-redux提供的,需要引入react-redux.
【1】设计state(设计state的原则是像设计数据库表的原则一样,此外还要注意扁平化,不要有很多层级,切忌按照页面需求或是后端接口返回的数据来设计)
按照功能分,包括查询显示和增改操作(项目很小可以不要分,但是为了练习,就划分一下),将state分成所有的待办项目,和当前查询条件
也就是,所有待办项目:
[
{id:0,name:'工作',haveDone:false}
....
]
以及当前查询:‘All’
设计好了state,我们就可以设计action和reducer了,action和reducer也按照设计的state一样分为增改操作的和查询操作的。
对于增改操作的,action.type分别为add和toggle(置完成和未完成),reducer是对这两个action的操作。我将action和reducer写到一个文件中了,可以分开,但是我看有文档上推荐将相关的action和reducer写到一个文件中的组织方式,所以就这样用了。
查询部分,按照查询的条件,action.filter包括All,Done,Undo
【2】将多个reducer合并成一个
【3】开始设计组件,设计组件包括展示组件和容器组件,其中展示组件只负责按照数据进行展示,不负责逻辑处理,容器组件负责逻辑处理,一般可以通过connect将展示组件与容器组件连接【在项目组织中可以将容器组件和展示组件放到不同的文件夹中,本例子中由于展示组件只在固定的容器组件中用到,所以将展示组件和对应的容器组件写到了一起】
本例子中用了三个容器组件
【容器组件介绍--添加】--具体代码如下
import {connect} from 'react-redux';
import React,{Component} from 'react';
import {addAction} from '../redux/update.js';
class inAddcom extends Component
{
constructor(props){
super(props);
this.input='';
}
clickHandle=()=>{
this.props.addClick(this.input.value);//调用mapDispatchToProps提供的addClick方法
this.input.value='';
}
render(){
return(
<div>
<input type='text' ref={node => {
this.input = node;
}} />
<button onClick={this.clickHandle}>添加</button>
</div>)
}
}
const mapDispatchToProps=(dispatch)=>({
addClick:(name)=>{
if(name&&name.trim()){
dispatch(addAction(name));//发送action
}
}
});
const AddCom=connect(null,mapDispatchToProps)(inAddcom);//通过connect连接
export default AddCom;
【列表介绍】代码如下:
import {connect} from 'react-redux';
import React,{Component} from 'react';
import {toggleAction} from '../redux/update.js';
class inList extends Component{
render(){
const {state ,bookClick}=this.props;
return(
<ul>
{state.map(cur=>{
let style={textDecoration:cur.haveDone? 'line-through':'none'};
return <li key={cur.id} style={style} onClick={()=>{bookClick(cur.id)}}>{`${cur.name}`}</li>
}
)
}
</ul>
)
}
}
const filterData=(stateData,filter)=>{
switch(filter){
case 'All':
return stateData;
case 'Done':
return stateData.filter(cur=> cur.haveDone);
case 'Undo':
return stateData.filter(cur=> !cur.haveDone);
}
}
const mapStateToProps=(state)=>({
state:filterData(state.updateReducer,state.queryReducer)
})
const mapDispatchToProps=(dispatch)=>({
bookClick:(id)=>{
dispatch(toggleAction(id));
}
})
const ToDoList=connect(mapStateToProps,mapDispatchToProps)(inList);
export default ToDoList;
【筛选条件介绍】代码如下:
import React,{Component} from 'react';
import {connect} from 'react-redux';
import {queryDoneAction} from '../redux/query.js';
class inButtonCom extends Component{
render(){
let {state,ButtonClick} =this.props;
return(
<div>
<button style={{backgroundColor:state=="All"?"#e4e4e4":"#ffffff"}} onClick={()=>{ButtonClick("All")}}>全部</button>
<button style={{backgroundColor:state=="Done"?"#e4e4e4":"#ffffff"}} onClick={()=>{ButtonClick("Done")}}>已完成</button>
<button style={{backgroundColor:state=="Undo"?"#e4e4e4":"#ffffff"}} onClick={()=>{ButtonClick("Undo")}}> 未完成</button>
</div>
)
}
}
let mapStateToProps=(state)=>({
state:state.queryReducer
})
let mapDispatchToProps=(dispatch)=>({
ButtonClick:(filter)=>{
dispatch(queryDoneAction(filter));
}
})
let ButtonCom= connect(mapStateToProps,mapDispatchToProps)(inButtonCom);
export default ButtonCom;
就这样,不涉及到数据库存储的小demo完成了!