Redux个人学习指南

前面的话

说实话,官方文档真的写得不行,它不是基于实例的教学,而是基于抽象的教学,让人想起了数据结构课本,代码例子中的很多变量都是突兀地呈现出来,让人摸不着头脑,于是我删了很多东西。

因此,这篇博客是基于原文档的一篇学习POST,但是在原文档的基础上增删了很多东西,并加入了自己的想法。

Redux

1. 先简单了解什么是Redux?

图片转载至蒙朦的文章
在这里插入图片描述
首先为什么我感觉看Redux的文档很吃力,这是因为我是先学的react,对应上图中的Component,而文档是从Action开始讲解的,而且递归的定义了很多变量,直接就把人绕进去了。

2. 如何理解Redux的设计理念

我才刚学Redux不到20min,我暂时是这么理解的。

首先,state存储在store里,并且被Component订阅(subscribe),当组件的state要改变时,它只能触发(trigger)Action,而Action不能直接访问store,必须要调度(dispatch)Reducer来帮她改变Store。

3. Action

3.1 什么是Action

官网定义如下

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

3.2 Action

Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。

{
  type: 'ADD_TODO',
  text: '学数学'
}

3.3 Action创建函数

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

上面提到过,Action实际上是一个普通的js对象,那么Action创建函数就是一个简单的可以返回js对象的函数。

function addTodo(text) {
  return {
    type: 'ADD_TODO',
    text: text
  }
}

由于action是由Reducer的dispatch调度的,那么我们可以直接这么写。

const boundAddTodo = text => dispatch(addTodo(text))

然后直接调用它们:

boundAddTodo("学数学");

3.3 Action的原则及注意事项(不断补充)

  • 我们应该尽量减少在 action 中传递的数据
    例如在Todo应用中,传递item的index要比把整个item传过去要好

4. Reducer

4.1什么是Reducer

Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。

4.2 设计State结构

在处理上一节提到的Action之前,我们需要先来设计State结构。 在 Redux 应用中,所有的 state 都被保存在一个单一对象中。建议在写代码前先想一下这个对象的结构。如何才能以最简的形式把应用的 state 用对象描述出来?

以 todo 应用为例:

  1. 完整的任务列表。
{
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}

4.3 处理上一节提到的Action

我们已经确定了 state 对象的结构,而且处理Action必须要用到Reducer,现在就可以开始开发 reducer。reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。

(previousState, action) => newState

永远不要在 reducer 里做这些操作:

  1. 修改传入参数;
  2. 执行有副作用的操作,如 API 请求和路由跳转;
  3. 调用非纯函数,如 Date.now() 或 Math.random()。

在高级篇里会介绍如何执行有副作用的操作。现在只需要谨记 reducer 一定要保持纯净。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。

我们之前说过,Reducer就是一个纯函数,用来接收旧的 state 和 action,返回新的 state。

const initialState = {
  todos: []
};

function todoApp(state = initialState, action) {
  // 当state为undefined时,赋值为默认初值
  // 这里暂不处理任何 action,
  // 仅返回传入的 state。
  return state
}
function todoApp(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    default:
      return state
  }
}

上面代码的意思是,如果接收的action的类型是’ADD_TODO’,意为添加一条新的待办事项。返回值是一个新的对象(state),这个对象是由旧的state和action的新TODO共同确定的。因为我们说过,不能直接更改state,因此需要返回一个新的对象(深拷贝),不懂的可以查一下Object.assign()函数。如果出现了意料之外的action.type,则不改变state。

4.4 合并Redecer

假设我们还有一个action,切换TODO的状态(未完成 - 已完成),那么我们可以编写两个Reducer,并在最后合并。

假设为了代码的耦合性能低一些,我们将添加todo、切换todo状态的Reducer拆开。而现在我们需要将其合为一个Reducer并暴露出去。

import { combineReducers } from 'redux'

const todoApp = combineReducers({
  toggle,
  todo
})

export default todoApp

4.5 Reducer的原则及注意事项(不断补充)

  1. 开发复杂的应用时,不可避免会有一些数据相互引用。建议你尽可能地把 state 范式化,不存在嵌套。把所有数据放到一个对象里,每个数据以 ID 为主键,不同实体或列表间通过 ID 相互引用数据。把应用的 state 想像成数据库。这种方法在 normalizr 文档里有详细阐述。例如,实际开发中,在 state 里同时存放 todosById: { id -> todo } 和 todos: array 是比较好的方式,本文中为了保持示例简单没有这样处理。
  2. 保持 reducer 纯净非常重要。永远不要在 reducer 里做这些操作:
    • 修改传入参数;
    • 执行有副作用的操作,如 API 请求和路由跳转;
    • 调用非纯函数,如 Date.now() 或 Math.random();
  3. 高级篇里会介绍如何执行有副作用的操作。现在只需要谨记 reducer 一定要保持纯净。只要传入参数相同,返回计算得到的下一个 state 就一定相同。没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。

5. Store

在前面的章节中,我们学会了使用 action 来描述“发生了什么”,和使用 reducers 来根据 action 更新 state 的用法。

5.1 Store提供的一些方法

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

维持应用的 state;
提供 getState() 方法获取 state;
提供 dispatch(action) 方法更新 state;
通过 subscribe(listener) 注册监听器;
通过 subscribe(listener) 返回的函数注销监听器。返回值是一个函数,直接执行就可以注销。

6. 自己的案例展示

npm install -g create-react-app
create-react-app redux-learning
cd redux-learning
npm install --save redux react-redux
npm run start
发布了113 篇原创文章 · 获赞 6 · 访问量 7109

猜你喜欢

转载自blog.csdn.net/swallowblank/article/details/103910590
今日推荐