上一篇大致介绍了Redux的状态流程。其中Action出镜率很高,本篇就介绍一下Action。源码已上传Github,第二篇源代码请参照src/originReduxAction文件夹。
Action的本质是个描述已发生事件,能携带数据的plain object。作用是告知Reducer该更新Store里哪些state。而且根据Flux标准,需要是一个有type属性的plain object。典型的样子:
const ADD_TODO = 'ADD_TODO'; { type: 'ADD_TODO', payload: { text: 'Do something.' } } { type: 'ADD_TODO', payload: new Error(), error: true }
在Reducer里通过收到的Action的不同type值,去执行不同的修改state的行为。type属性通常会被定义成常量字符串或Symbol对象,而且常量字符串通常会被统一放在config文件中,便于管理。当然,这不是必须的,如果你的应用非常小,type属性直接赋值字符串也没问题,只要保证唯一就行。
通常来说同步Action设type就够了。异步Action,除了必须的type属性外,根据Flux标准,你还可以添加payload ,error,meta属性。
payload属性:顾名思义就是Action的额外的信息,可以设任意类型的值。通常当error属性为true时,payload会赋值error对象,例如rejected的promise信息。
error属性:当Action发生错误时,设为true。如果该属性为true以外的值,包括undefined或null,都认为Action没有错误。
meta属性:不适合放到payload里的信息,可以放到这个属性里,同样可以设任意类型的值。
除了上述4种属性,其实你还可以为Action对象添加任意属性,这完全由你自己决定。
现在我们将上一篇的例子代码,改造一下,目录结构如下,新建actions目录,将Action独立出来,新建configs目录存放Action的type值常量,最后将含DOM结构的源代码放入entries主目录:
actions/number.js:(这里补充一个小概念,Action是个plain object没错,但每次dispatch一个对象代码写起来麻烦。通常我们会如下创建个Action creator,即创建Action的函数。这样dispatch时,代码就能简化成store.dispatch(actions.incrementNum());)
import * as constant from '../configs/action'; export const incrementNum = () => ({ type: constant.INCREMENT, }); export const decrementNum = () => ({ type: constant.DECREMENT, }); export const clearNum = () => ({ type: constant.CLEAR_NUM, });
configs/action.js:
export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; export const CLEAR_NUM = 'CLEAR_NUM';
entries/originReduxAction.js:
// 改前 addNum = () => { store.dispatch({ type: 'INCREMENT' }); }; minusNum = () => { store.dispatch({ type: 'DECREMENT' }); }; clearNum = () => { store.dispatch({ type: 'CLEAR_NUM' }); }; // 改后 addNum = () => { store.dispatch(actions.incrementNum()); }; minusNum = () => { store.dispatch(actions.decrementNum()); }; clearNum = () => { store.dispatch(actions.clearNum()); };
最终结果和第一篇是一样的,如下图数字会跟随点击的按钮发生变化。例子本身的结果不重要。重要的是代码的结构更加工程化,后几篇会继续完善代码结构。
最后重复一下Action的本质:是个描述已发生事件,能携带数据的plain object。使用Redux框架的话,你只能通过分派Action来修改state,不能直接修改Store里的state。这样代码更加可控,出了问题溯源起来更加方便。有关异步Action将在异步操作中介绍,但不管同步还是异步,Action的本质都是一样的。