🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Action 首先,让我们来给 action 下个定义。 **Actions** 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的**惟一**来源。用法是通过 [`store.dispatch()`](#) 把 action 传到 store。 添加新 todo 任务的 action 是这样的: ~~~ const ADD_TODO = 'ADD_TODO'; ~~~ ~~~ { type: 'ADD_TODO', text: 'Build my first Redux app' } ~~~ Action 本质是 JavaScript 普通对象。我们约定,action 内使用一个字符串类型的 `type` 字段来表示将要执行的动作。多数情况下,`type` 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。 ~~~ import { ADD_TODO, REMOVE_TODO } from '../actionTypes'; ~~~ > ##### 样板文件使用提醒 > 使用单独的模块或文件来定义 action type 常量并不是必须的,甚至根本不需要定义。对于小应用来说,使用字符串做 action type 更方便些。不过,在大型应用中最多把它们显式地定义成常量。参照 [减少样板代码](#) 获取保持代码干净的实践经验。 除了 `type` 字段外,action 对象的结构完全取决于你。参照 [Flux 标准 Action](https://github.com/acdlite/flux-standard-action) 获取如何组织 action 的建议。 这时,我们还需要再添加一个 action type 来标记任务完成。因为数据是存放在数组中的,我们通过 `index` 来标识任务。实际项目中一般会在新建内容的时候生成惟一的 ID 做标识。 ~~~ { type: COMPLETE_TODO, index: 5 } ~~~ **action 中传递的数据越少越好**。比如,这里传递 `index` 就比把整个任务对象传过去要好。 最后,再添加一个 action 类型来表示当前展示的任务状态。 ~~~ { type: SET_VISIBILITY_FILTER, filter: SHOW_COMPLETED } ~~~ ### Action 创建函数 **Action 创建函数** 就是生成 action 的方法。“action” 和 “action 创建函数” 这两个概念很容易混在一起,使用时最好注意区分。 在 [传统的 Flux](http://facebook.github.io/flux) 实现中,当调用 action 创建函数时,一般会触发一个 dispatch,像这样: ~~~ function addTodoWithDispatch(text) { const action = { type: ADD_TODO, text }; dispatch(action); } ~~~ 不同的是,Redux 中的 action 创建函数是 **纯函数**,它没有任何副作用,只是返回 action 对象而已。 ~~~ function addTodo(text) { return { type: ADD_TODO, text }; } ~~~ 这让代码更易于测试和移植。只需把 action 创建函数的结果传给 `dispatch()` 方法即可实例化 dispatch。 ~~~ dispatch(addTodo(text)); dispatch(completeTodo(index)); ~~~ 或者创建一个 **被绑定的 action 创建函数** 来自动 dispatch: ~~~ const boundAddTodo = (text) => dispatch(addTodo(text)); const boundCompleteTodo = (index) => dispatch(CompleteTodo(index)); ~~~ 可以这样调用: ~~~ boundAddTodo(text); boundCompleteTodo(index); ~~~ store 里能直接通过 [`store.dispatch()`](#) 调用 `dispatch()` 方法,但是多数情况下你会使用 [react-redux](http://github.com/gaearon/react-redux) 提供的 `connect()` 帮助器来调用。[`bindActionCreators()`](#) 可以自动把多个 action 创建函数 绑定到 `dispatch()` 方法上。 ### 源码 ### `actions.js` ~~~ /* * action 类型 */ export const ADD_TODO = 'ADD_TODO'; export const COMPLETE_TODO = 'COMPLETE_TODO'; export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'; /* * 其它的常量 */ export const VisibilityFilters = { SHOW_ALL: 'SHOW_ALL', SHOW_COMPLETED: 'SHOW_COMPLETED', SHOW_ACTIVE: 'SHOW_ACTIVE' }; /* * action 创建函数 */ export function addTodo(text) { return { type: ADD_TODO, text }; } export function completeTodo(index) { return { type: COMPLETE_TODO, index }; } export function setVisibilityFilter(filter) { return { type: SET_VISIBILITY_FILTER, filter }; } ~~~ ### 下一步 现在让我们 [开发一些 reducers](#) 来指定发起 action 后 state 应该如何更新。 > ##### 高级用户建议 > 如果你已经熟悉这些基本概念且已经完成了这个示例,不要忘了看一下在 [高级教程](#) 中的 [异步 actions](#),你将学习如何处理 AJAX 响应和如何把 action 创建函数组合成异步控制流。