redux 的概述

随着 javascript 单页应用的不断发展,javascript 需要管理比以往都要多的状态,管理不断变化的 state 非常困难,数据流动不断变的模糊不可预测,代码的开发与维护成为了变得越来越困难.redux 这类状态管理框架变出现了,通过限制更新发生的时间和方式,来使 state 的变化变得可以预测.

redux 是一个很有用的框架,但是并不是非用不可,而是当你自己觉得可能需要 redux 的时候,就会找到他,并且使用他(还有其他同类框架)

  • 当你有大量的,随时间变化的数据
  • 当你需要一个单一可靠的 state 数据源
  • 当你把所有 state 放到顶部,或者父子兄弟之间的数据通信让你焦头烂额的时候

三大原则

  1. 单一数据源 (整个应用的 state 存放在一个 object tree 中,这个 object tree 只存在与唯一的一个 store 中)
  2. state 是只读的,唯一能够改变 state 的只有 action
  3. 只能通过纯函数进行修改

state 基本概念

state 是数据的状态集合,一般为一个对象

let state = {
singer: [
{
name: "刘德华",
desc: "一位演员"
}
],
actor: [
{
name: "郭富城",
desc: "一位歌手"
}
]
};

action 基本概念

action 是一个普通的 javacript 对象,用来更新 state 并同时描述发生了什么.可以知道应用到底发生了什么,变化后可以知道为什么改变.

let action = {
type: "ADD_SINGER",
payload: {
name: "黎明",
desc: "一位很好的歌手"
}
}; let action2 = {
type: "ADD_ACTOR",
payload: {
name: "周润发",
desc: "一位很好的演员"
}
};

action 生成器

(action 是一个对象,action 生成器是一个函数,两个不同的概念)

用于 action 的复用,实际上是返回一个对象的函数

function addSinger_action(payload) {
return {
type: "ADD_SINGER",
payload
};
} function addActor_action(payload) {
return {
type: "ADD_ACTOR",
payload
};
}

reducer 基本概念

reducer 是一个为了把 state 和 action 连接起来而诞生的纯函数,接收 state 和 action,然后返回一个新的 state

function add_singer(state, action) {
if (action.type === "ADD_SINGER") {
console.warn("发起了action=ADD_SINGER");
state = Object.assign({}, state, {
singer: state.singer.concat([action.payload])
});
return state;
}
return state;
} function add_actor(state, action) {
if (action.type === "ADD_ACTOR") {
console.warn("发起了action=>ADD_ACTOR");
state = Object.assign({}, state, {
actor: state.actor.concat([action.payload])
});
return state;
}
return state;
}

改变 state

state = add_actor(
state,
addActor_action({
name: "周润发",
desc: "一位很好的演员"
})
); console.log(state); state = add_singer(
state,
addSinger_action({
name: "黎明",
desc: "一位很好的歌手"
})
); console.log(state);

上面就是 state,action 以及 reducer 连接二者的方式,redux 里面提供了更多的便捷操作

redux 基础

1. redux 中的 action

action 主要是把数据从应用传到 store 的有效载荷,它是 store 的唯一来源,通过 reducer 定义的 state 是初始化,一般写法中多设置为 null,undefined,{},[]等.通过 store.dispatch()将 action 传到 store.为了使用方便,一般会用 action 生成器来生成 action.

redux 只用把 action 生成器的结果传给 dispatch()就可以发起 dispatch

import { createStore } from "../redux/index";
import reducer from './reducer'; const ADD_SINGER = "ADD_SINGER";
const ADD_ACTOR = "ADD_ACTOR"; const store = createStore(reducer); store.dispatch(
addSinger_action({
name: "周华健",
desc: "一位大帅哥"
})
); store.dispatch(
addActor_action({
name: "谢安琪",
desc: "一位小美女"
})
); console.log(store.getState()); function addSinger_action(payload) {
return {
type: ADD_SINGER,
payload
};
}
function addActor_action(payload) {
return {
type: ADD_ACTOR,
payload
};
}

我们也可以创建一个函数用于返回 dispatch 触发器
bound_add_singer_action({
name: "周华健",
desc: "一位大帅哥"
}); bound_add_actor_action({
name: "谢安琪",
desc: "位小美女"
}); function bound_add_singer_action(payload) {
return store.dispatch(addSinger_action(payload));
} function bound_add_actor_action(payload) {
return store.dispatch(addActor_action(payload));
} console.log(store.getState());

action 主要包含 action 对象,action_creater()生成器,bound_action_creater()绑定函数

//我是action
{type:"我是type",payload:"我是数据"} //我是action生成器,我是来返回action对象
function action_creater(){
return {type:"我是type",payload:"我是数据"}
} //我是bound_action_creater绑定函数,我是获取action生成器的返回值去触发dispatch()
function bound_action_creater(){
store.dispatch(action_creater());
}

2. redux 中 reducer

(oldState,action)=> newState 这种就是一个最简单的 reducer.

禁止事项

  1. 修改传入的参数
  2. 执行有副作用的操作,如 api 请求,变量修改,路由跳转
  3. 调用非纯函数,如 Date.now()或 Math.random()
const singerState = {
singer: [
{
name: "刘德华",
desc: "一位演员"
}
]
}; //state初始状态 const actorState = {
actor: [
{
name: "郭富城",
desc: "一位歌手"
}
]
}; //state初始状态 const reducer = function(state = {}, action) {
return {
singerState: singer_reducer(state.singerState, action),
actorState: actor_reducer(state.actorState, action)
};
};
// console.log(reducer); export default reducer; function singer_reducer(state = singerState, action) {
if (action.type === "ADD_SINGER") {
console.warn("发起了action=ADD_SINGER");
state = Object.assign({}, state, {
singer: state.singer.concat([action.payload])
}); //Object.assgin会修改第一个参数的值,所以将state放到二号位
return state;
}
return state; //遇到未知的 action 时,一定要返回旧的 state
} function actor_reducer(state = actorState, action) {
if (action.type === "ADD_ACTOR") {
console.warn("发起了action=>ADD_ACTOR");
state = Object.assign({}, state, {
actor: state.actor.concat([action.payload])
});
return state;
}
if (action.type === "MINUS_ACTOR") {
console.warn("发起了action=>MINUS_ACTOR");
let actor = [].concat(state.actor);
state = Object.assign({}, state, {
actor: actor.splice(action.index, 1)
});
return state;
}
return state;
}

redux 当然提供了的便捷方法 combineReducers().combineReducers()只是生成一个函数 combination,这个函数将调用所有的 reducer,每个 reducer 根据 key 值筛选出 state 的一部分数据进行处理.这个函数再将所有的 reducer 结果合成一个大对象.

import { combineReducers } from "../redux/index";

// 返回一个combination函数
const reducer = combineReducers({
singer_reducer,
actor_reducer
}); // console.log(reducer);

此时在 store 中,数据的 key 值会变为 singer_reducer 和 actor_reducer,我们可以通过设置不同 key 来更改在 store 中存放的 key

{
singerState:singer_reducer,
actorState:actor_reducer
}
//或者将函数名更改

3. redux 中 store

  • store 维护应用的 state
  • 提供 getState()方法获取 state
  • 提供 dispatch()方法触发 action,更新 state (action->reducer->newState)
  • subscribe()注册监听器
  • subscribe()返回一个函数用来注销监听器

const store = createStore(reducer);

const unsubscribe = store.subscribe(listener);

bound_add_singer_action({
name: "周华健",
desc: "一位大帅哥"
}); bound_add_actor_action({
name: "谢安琪",
desc: "位小美女"
}); bound_minus_actor_action(1); unsubscribe(); bound_add_singer_action({
name: "周杰伦",
desc: "歌手一枚"
}); bound_add_actor_action({
name: "周星驰",
desc: "笑了"
}); function listener() {
console.log(store.getState());
} function bound_add_singer_action(payload) {
return store.dispatch(addSinger_action(payload));
} function bound_add_actor_action(payload) {
return store.dispatch(addActor_action(payload));
} function bound_minus_actor_action(index) {
return store.dispatch(minusActor_action(index));
}

当我们 shore.dispatch()之后返回的值就是一个用来注销该监听器的 unsubscribe 函数,redux 中源码:

  function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
} let isSubscribed = true ensureCanMutateNextListeners()
<!-- 将listener推入到执行队列中去 -->
nextListeners.push(listener) return function unsubscribe() {
if (!isSubscribed) {
return
} isSubscribed = false ensureCanMutateNextListeners()
<!-- 找到监听的listener,并将函数从队列中删除 -->
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}

第一个 Redux 中文文档

第二个 Redux 中文文档

Redux 官方文档

Redux 简明教程

Understand Redux

Redux 入门教程(三):React-Redux 的用法

[Redux] redux的概述的更多相关文章

  1. Flux --> Redux --> Redux React 入门

    本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...

  2. [React] 11 - Redux: redux

    Ref: Redux中文文档 Ref: React 讀書會 - B團 - Level 19 Redux 深入淺出 Ref: React+Redux 分享會 Ruan Yifeng, Redux 架构: ...

  3. Flux --> Redux --> Redux React 基础实例教程

    本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...

  4. Flux --> Redux --> Redux React 入门 基础实例使用

    本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...

  5. 基于 Redux + Redux Persist 进行状态管理的 Flutter 应用示例

    好久没在 SegmentFault 写东西,唉,也不知道 是忙还是懒,以后有时间 再慢慢写起来吧,最近开始学点新东西,有的写了,个人博客跟这里同步. 一直都在自己的 React Native 应用中使 ...

  6. [Redux] Redux: Extracting Container Components -- AddTodo

    Code to be refactored: const AddTodo = ({ onAddClick }) => { let input; return ( <div> < ...

  7. [Redux] redux之combineReducers

    combineReducers combineReducer 是将众多的 reducer 合成通过键值映射的对象,并且返回一个 combination 函数传入到 createStore 中 合并后的 ...

  8. [React] 14 - Redux: Redux Saga

    Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga  [入门] Ref: 从redux-thun ...

  9. redux 简介

    概述 Redux 本身是个极其简单的状态管理框架, 它的简单体现在概念少, 流程明确. 但是, 正是因为简单, 使用上没有强制的约束, 所以如果用不好, 反而会让状态管理更加混乱. 我觉得, 用好 R ...

随机推荐

  1. Runnable与Callable区别

    相同点: 两者都是接口:(废话) 两者都可用来编写多线程程序: 两者都需要调用Thread.start()启动线程: 不同点: 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果:而 ...

  2. 解决maven在build时下载文件卡死问题

    1.停止build 2.cd ~/.m2/repository 3.在这个目录下找到你要下载的文件,然后查看是否有个同名文件带一个.lock后缀 4.rm -f   xxxx.lock 5.重新bui ...

  3. linux 最为常用的命令

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 cat /proc/cpuinfo 显示CPU info的信息 ...

  4. uiautomatorviewer 优化定位符生成,支持生成Java,Python自动化代码

    项目介绍 二次开发 uiautomatorviewer 优化定位符生成,支持生成Java,Python自动化代码,修复自带工具画面有动态加载时截图失败问题,优化自带工具截图速度 ,实现类似录制脚本功能 ...

  5. TCP的客户端搭建

    一.设计目标 之前已经写过了TCP服务器原理及通过visual studio 验证 SOCKET编程:搭建一个TCP服务器,这里我们搭建一个TCP客户端界面并对各功能进行实现.设计效果如下: 二.实验 ...

  6. 兆芯 服务器 win2012/win7装机总结

    兆芯cpu 服务器 win2012/win7装机总结 一.设置U盘启动装机 启动后,esc进入bios修改下图两个地方,都要改,然后保存. 二.重启计算机,进入win安装界面,会出现无法安装,原因是: ...

  7. MFC之几类消息的区别

    1.ON_COMMAND与ON_UPDATE_COMMAND_UI 开发MFC程序,给菜单子项添加消息处理函数时,会碰到ON_COMMAND和ON_UPDATE_COMMAND_UI两个消息. ON_ ...

  8. win10个人助理conrtana软件能否支持用户反馈、后续优化

    上网查找了一下,win10的个人助理不支持用户反馈.这些反馈都是用户通过别的途径来发表反馈的信息,这个缺陷让用户不是特别满意,因为反馈信息不再那么简答,变得越来越繁琐.有些人还会担心自己反馈的问题会不 ...

  9. Windows 10 IoT Core 17127 for Insider 版本更新

    昨天,微软发布了Windows 10 IoT Core 17127 for Insider 版本更新,本次更新只修正了一些Bug,没有发布新的特性.相比于17120,修复了一个已知的问题. 一些已知的 ...

  10. 数据结构图解(递归,二分,AVL,红黑树,伸展树,哈希表,字典树,B树,B+树)

    递归反转 二分查找 AVL树 AVL简单的理解,如图所示,底部节点为1,不断往上到根节点,数字不断累加. 观察每个节点数字,随意选个节点A,会发现A节点的左子树节点或右子树节点末尾,数到A节点距离之差 ...