目标

理解redux的action,reducer,store,数据流等概念,并以此基础产出demo。

1.Action

概念:

Action 是把数据从应用(这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。

Action创建函数:

Action 创建函数 就是生成 action 的方法。“action” 和 “action 创建函数” 这两个概念很容易混在一起,使用时最好注意区分。
创建Action.js文件

  1. const Action=function(text){
  2. return {
  3. type:'ADD_TODO',
  4. text:text
  5. }
  6. }
  7. export default Action


2.Reducer

Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
Reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。它会跟action发送过来的type类型做逻辑处理。

约束
•不得改写参数
•不能调用系统 I/O 的API
•不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果
Reducer 函数里面不能改变 State,必须返回一个全新的对象,如下面的写法。
// State 是一个对象
function reducer(state, action) {
return Object.assign({}, state, { thingToChange });
// 或者
return { …state, …newState };
}
// State 是一个数组
function reducer(state, action) {
return […state, newItem];
}
创建Reducer.js文件

  1. const Reducer=function(state,action){
  2. if(typeof state === 'undefined'){
  3. return []
  4. }
  5. switch (action.type){
  6. case 'ADD_TODO':
  7. return [...state,action.text]
  8. break;
  9. default:
  10. return state;
  11. break;
  12. }
  13. }
  14. export default Reducer;


3.Store

action 来描述“发生了什么”,和使用 reducers 来根据 action 更新 state 的用法。

Store 就是把它们联系到一起的对象。Store 有以下职责:

  • 维持应用的 state;
  • 提供 getState() 方法获取 state;返回应用当前的 state 树。它与 store 的最后一个 reducer 返回值相同。
  • 提供 dispatch(action) 方法更新 state;分发 action。这是触发 state 变化的惟一途径。
  • 通过 subscribe(listener) 注册监听器; 添加一个变化监听器。每当 dispatch action 的时候就会执行,state 树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state。
  • 通过 subscribe(listener) 返回的函数注销监听器。

再次强调一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合 而不是创建多个 store。

创建一个store我们只需要从createStore 这个API。
创建Store.js文件

  1. import {createStore} from 'redux';
  2. import Reducer from './Reducer';
  3. const Store=createStore(Reducer)
  4. export default Store;

至此,我们已经创建好啦action,reducer,store这三个在redux最核心的东西,那么接下来我们就创建视图层,通过视图层发起action,来使得整个demo连贯起来。

创建View.js文件

  1. import React from 'react';
  2. import Action from './Action'
  3. import Store from './Store'
  4. class Demo extends React.Component{
  5. constructor(props){
  6. super(props)
  7. this.state={
  8. str:Store.getState() //获取store处理后的所有数据
  9. }
  10. this.itemchange=this.itemchange.bind(this)
  11. }
  12. //数据变更之后需要函数的监听来调用setState,来实现render的重新渲染
  13. itemchange(){
  14. var data=Store.getState();
  15. this.setState({str:data})
  16. }
  17. componentDidMount(){
  18. Store.subscribe(this.itemchange) // 监听数据改变
  19. }
  20. tap(){
  21. Store.dispatch(Action(this.refs.ipt.value)) //发起action
  22. }
  23. render(){
  24. return(
  25. <div>
  26. <h1>redux</h1>
  27. <input type="text" ref="ipt"/>
  28. <button onClick={this.tap.bind(this)}>添加</button>
  29. <hr/>
  30. {
  31. this.state.str.map((item,i)=>{
  32. return (
  33. <div key={i}>
  34. {item}
  35. </div>
  36. )
  37. })
  38. }
  39. </div>
  40. )
  41. }
  42. }
  43. export default Demo;

附录一个文件创建目录

image.png

4.数据流

严格的单向数据流是 Redux 架构的设计核心。
这意味着应用中所有的数据都遵循相同的生命周期,这样可以让应用变得更加可预测且容易理解。同时也鼓励做数据范式化,这样可以避免使用多个且独立的无法相互引用的重复数据。

1.调用store.dispatch(action)

Action 就是一个描述“发生了什么”的普通对象 比如我们上边的action

  1. {
  2. type:'ADD_TODO',
  3. text:text
  4. }


2.Redux store 调用传入的 reducer 函数

Store 会把两个参数传入 reducer: 当前的 state 树和 action

3.根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树。**

根 reducer 的结构完全由你决定。Redux 原生提供combineReducers()辅助函数,来把根 reducer 拆分成多个函数,用于分别处理 state 树的一个分支。

4.Redux store 保存了根 reducer 返回的完整 state 树

这个新的树就是应用的下一个 state!所有订阅 store.subscribe(listener) 的监听器都将被调用;监听器里可以调用 store.getState() 获得当前 state。
现在,可以应用新的 state 来更新 UI。如果你使用了 React Redux 这类的绑定库,这时就应该调用 component.setState(newState) 来更新。

**