Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redux 及其工作原理 #112

Open
yangtao2o opened this issue Apr 14, 2020 · 0 comments
Open

Redux 及其工作原理 #112

yangtao2o opened this issue Apr 14, 2020 · 0 comments

Comments

@yangtao2o
Copy link
Owner

yangtao2o commented Apr 14, 2020

Redux

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。Redux 由以下组件组成:

  • Action – 这是一个用来描述发生了什么事情的对象。
  • Reducer – 这是一个确定状态将如何变化的地方。
  • Store – 整个程序的状态/对象树保存在 Store 中。
  • View – 只显示 Store 提供的数据。

Redux 数据流动

Redux 遵循的三个原则:

单一事实来源:整个应用的状态存储在单个 store 中的对象/状态树里。单一状态树可以更容易地跟踪随时间的变化,并调试或检查应用程序。

状态是只读的:改变状态的唯一方法是去触发一个动作。动作是描述变化的普通 JS 对象。就像 state 是数据的最小表示一样,该操作是对数据更改的最小表示。

使用纯函数进行更改:为了指定状态树如何通过操作进行转换,你需要纯函数。纯函数是那些返回值仅取决于其参数值的函数。

简要描述:

  • redux 是的诞生是为了给 React 应用提供「可预测化的状态管理」机制。
  • Redux 会将整个应用状态(其实也就是数据)存储到到一个地方,称为 store
  • 这个 store 里面保存一棵状态树(state tree)
  • 组件改变 state 的唯一方法是通过调用 store 的 dispatch 方法,触发一个 action,这个 action 被对应的 reducer 处理,于是 state 完成更新
  • 组件可以派发(dispatch)行为(action)给 store,而不是直接通知其它组件
  • 其它组件可以通过订阅 store 中的状态(state)来刷新自己的视图

代码演示:

import { createStore } from "redux";

/* 创建reducer
 ** 可以使用单独的一个reducer,也可以将多个reducer合并为一个reducer,即:combineReducers()
 ** action发出命令后将state放入reucer加工函数中,返回新的state,对state进行加工处理
 */
const reducer = (state = { counter: 0 }, action) => {
  switch (action.type) {
    case "INCREASE":
      return { counter: state.counter + 1 };
    case "DECREASE":
      return { counter: state.counter - 1 };
    default:
      return state;
  }
};

/* 创建action
 ** 用户是接触不到state的,只能有view触发,所以,这个action可以理解为指令,需要发出多少动作就有多少指令
 ** action是一个对象,必须有一个叫type的参数,定义action类型
 */
const actions = {
  increase: () => ({ type: "INCREASE" }),
  decrease: () => ({ type: "DECREASE" }),
};

/* 创建的store,使用createStore方法
 ** store 可以理解为有多个加工机器的总工厂
 ** 提供subscribe,dispatch,getState这些方法。
 */
const store = createStore(reducer);

// 订阅
const unsubscribe = store.subscribe(() => console.log(store.getState()));

// 发起一系列 action
store.dispatch(actions.increase()); // {counter: 1}
store.dispatch(actions.increase()); // {counter: 2}
store.dispatch(actions.increase()); // {counter: 3}
store.dispatch(actions.decrease()); // {counter: 2}

// 停止监听 state 更新
unsubscribe();

Redux 与 Flux 有何不同?

Flux Redux
1. Store 包含状态和更改逻辑 1. Store 和更改逻辑是分开的
2. 有多个 Store 2. 只有一个 Store
3. 所有 Store 都互不影响且是平级的 3. 带有分层 reducer 的单一 Store
4. 有单一调度器 4. 没有调度器的概念
5. React 组件订阅 store 5. 容器组件是有联系的
6. 状态是可变 6. 状态是不可改变的

Redux 的优点如下:

  • 结果的可预测性 - 由于总是存在一个真实来源,即 store ,因此不存在如何将当前状态与动作和应用的其他部分同步的问题。
  • 可维护性 - 代码变得更容易维护,具有可预测的结果和严格的结构。
  • 服务器端渲染 - 你只需将服务器上创建的 store 传到客户端即可。这对初始渲染非常有用,并且可以优化应用性能,从而提供更好的用户体验。
  • 开发人员工具 - 从操作到状态更改,开发人员可以实时跟踪应用中发生的所有事情。
  • 社区和生态系统 - Redux 背后有一个巨大的社区,这使得它更加迷人。一个由才华横溢的人组成的大型社区为库的改进做出了贡献,并开发了各种应用。
  • 易于测试 - Redux 的代码主要是小巧、纯粹和独立的功能。这使代码可测试且独立。
    组织 - Redux 准确地说明了代码的组织方式,这使得代码在团队使用时更加一致和简单。

关于 Redux 的资料:

React-Redux

React Redux 将组件区分为 容器组件 和 UI 组件:

  • 前者会处理逻辑
  • 后者只负责显示和交互,内部不处理逻辑,状态完全由外部掌控

两个核心:

  • Provider 顶层组件,目的是让所有组件都能够访问到 Redux 中的数据

  • connect:connect(mapStateToProps, mapDispatchToProps)(MyComponent)

    • mapStateToProps - 把 Redux 中的数据映射到 React 中的 props 中去
    • mapDispatchToProps - 把各种 dispatch 变成了 props 让你可以直接使用

DEMO:实现计数器,完整 Demo 可以看这里

学习资料:

Redux 中间件

我们使用 redux-thunk 在 React 中调用 API。因为 reduce 是纯函数,所以没有副作用,比如调用 API。

因此,我们必须使用 redux-thunk 从 Action creators 那里进行 API 调用。Action creator 派发一个 action,将来自 API 的数据放入 action 的 payload 中。Reducers 接收数据,其余的过程也是相同的。

redux-thunk 是一个中间件。一旦它被引入到项目中,每次派发一个 action 时,都会通过 thunk 传递。如果它是一个函数,它只是等待函数处理并返回响应。如果它不是一个函数,它只是正常处理。

举个栗子:sendEmailAPI 是从组件中调用的函数,它接受一个数据并返回一个函数,其中 dispatch 作为参数。我们使用 redux-thunk 调用 API apiservice,并等待收到响应。一旦接收到响应,我们就使用 payload 派发一个 action。

import apiservice from "../services/apiservice";

export function sendEmail(data) {
  return { type: "SEND_EMAIL", payload: data };
}

export function sendEmailAPI(email) {
  return function(dispatch) {
    return apiservice.callAPI(email).then((data) => {
      dispatch(sendEmail(data));
    });
  };
}

其他中间件:

  • redux-saga
  • redux-thunk
  • redux-promise

学习资料:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant