实现需求:
1,项目中引入 redux :
npm install --save redux
2,首先在入口文件中 创建一个 store 对象
store 对象中要传入一个 reducer ,完成 reducer之前,假定 store 对象已经创建好,当store对象中的状态 state 发生改变的时候,需要订阅监听 state 的改变,并将这个store 对象中传给组件对象,组件对象再通过 getState 方法得到 store 中的状态。
3,接下来先完成 reducer对象,在 redux 文件夹中创建一个 reducers.js 文件,在其中写入一个 counter 函数(模块),并暴露这个模块,
reducer 中的模块,接收的参数是 state 和 action,state得到原来的状态值,根据 action(增删改查等操作)改变 state,得到一个新的 state,
其中 state 可以指定默认值,没有进行任何操作时,使 state 等于这个默认值,生成 reducer 对象时会得到这个初始化 state,组件对象可以渲染默认值
action.type 是 “ADD”,即用户的操作是增加时,state 值为原来的 state 加上 action操作中的data(即事件触发时传递的参数,如触发增加操作,传递增加的数量,触发删除操作,要传递删除对象的索引)
为了便于管理,将 ‘ADD’ 和 'CUT' 等 action常量字符串单独放置在一个模块中,在redux 文件夹中再新建一个 action-types.js 文件,然后在 reducers 中 引入 action-types 即可
4,接着可以在组件对象中获取 store 中的 state,并渲染
app.jsx
import React, { Component } from 'react' import {ADD,CUT} from '../../redux/action-types' export default class App extends Component { add=()=>{ const num=this.select.value*1; //select中选中的值是字符串,所以乘以1变为number类型 //调用store的方法更新状态 this.props.store.dispatch({type:ADD,num}) } cut=()=>{ const num=this.select.value*1 this.props.store.dispatch({type:CUT,num}) } addIfOdd=()=>{ const num=this.select.value*1; const oldcount=this.props.store.getState() //getState获取store中的state if(oldcount%2===1){ //state状态是奇数 this.props.store.dispatch({type:ADD,num}) } } addAsync=()=>{ const num=this.select.value*1; setTimeout(() => { this.props.store.dispatch({type:ADD,num}) },1000) } render() { const count=this.props.store.getState() return ( <div> <p>点击了{count}次</p> <select ref={select=>this.select=select}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select> <button onClick={this.add}>add +</button> <button onClick={this.cut}>cut -</button> <button onClick={this.addIfOdd}>addIfOdd</button> <button onClick={this.addAsync}>addAsync</button> </div> ) } }
有一个 地方需要注意,action 对象中的 data变量名要和组件对象传递的变量名一致,
这里不是 action.data,否则会出现 NaN
完善 redux
1,添加一个 生成 action 的模块,之前我们更新状态时,是自己生成的 action 来传递给 store 对象,
在 redux 中 再建一个 actions 文件,向文件中 写入 add和cut 两个 action
然后在组件中引入 actions,就不用自己生成 action 对象了
app.jsx
import React, { Component } from 'react' import * as actions from '../../redux/actions' //等价于import {add,cut} from '../../redux/actions' export default class App extends Component { add=()=>{ const num=this.select.value*1; //select中选中的值是字符串,所以乘以1变为number类型 //调用store的方法更新状态 this.props.store.dispatch(actions.add(num)) } cut=()=>{ const num=this.select.value*1 this.props.store.dispatch(actions.cut(num)) } addIfOdd=()=>{ const num=this.select.value*1; const oldcount=this.props.store.getState() //getState获取store中的state if(oldcount%2===1){ //state状态是奇数 this.props.store.dispatch(actions.add(num)) } } addAsync=()=>{ const num=this.select.value*1; setTimeout(() => { this.props.store.dispatch(actions.add(num)) },1000) } render() { const count=this.props.store.getState() return ( <div> <p>点击了{count}次</p> <select ref={select=>this.select=select}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select> <button onClick={this.add}>add +</button> <button onClick={this.cut}>cut -</button> <button onClick={this.addIfOdd}>addIfOdd</button> <button onClick={this.addAsync}>addAsync</button> </div> ) } }
2,添加一个生成 store 的模块,之前我们是在入口文件 index.js 中生成 store 对象,可以在 redux 中新建一个 store.js 文件用来生成 store 对象,并将 store 暴露,export default 暴露,只有一个store 对象
然后在入口文件中引入 store 模块即可
3,所以,最终 redux 共包含四个模块,