[Redux] redux的概述
redux 的概述
随着 javascript 单页应用的不断发展,javascript 需要管理比以往都要多的状态,管理不断变化的 state 非常困难,数据流动不断变的模糊不可预测,代码的开发与维护成为了变得越来越困难.redux 这类状态管理框架变出现了,通过限制更新发生的时间和方式,来使 state 的变化变得可以预测.
redux 是一个很有用的框架,但是并不是非用不可,而是当你自己觉得可能需要 redux 的时候,就会找到他,并且使用他(还有其他同类框架)
- 当你有大量的,随时间变化的数据
- 当你需要一个单一可靠的 state 数据源
- 当你把所有 state 放到顶部,或者父子兄弟之间的数据通信让你焦头烂额的时候
三大原则
- 单一数据源 (整个应用的 state 存放在一个 object tree 中,这个 object tree 只存在与唯一的一个 store 中)
- state 是只读的,唯一能够改变 state 的只有 action
- 只能通过纯函数进行修改
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.
禁止事项
- 修改传入的参数
- 执行有副作用的操作,如 api 请求,变量修改,路由跳转
- 调用非纯函数,如 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的概述的更多相关文章
- Flux --> Redux --> Redux React 入门
本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...
- [React] 11 - Redux: redux
Ref: Redux中文文档 Ref: React 讀書會 - B團 - Level 19 Redux 深入淺出 Ref: React+Redux 分享會 Ruan Yifeng, Redux 架构: ...
- Flux --> Redux --> Redux React 基础实例教程
本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...
- Flux --> Redux --> Redux React 入门 基础实例使用
本文的目的很简单,介绍Redux相关概念用法 及其在React项目中的基本使用 假设你会一些ES6.会一些React.有看过Redux相关的文章,这篇入门小文应该能帮助你理一下相关的知识 一般来说,推 ...
- 基于 Redux + Redux Persist 进行状态管理的 Flutter 应用示例
好久没在 SegmentFault 写东西,唉,也不知道 是忙还是懒,以后有时间 再慢慢写起来吧,最近开始学点新东西,有的写了,个人博客跟这里同步. 一直都在自己的 React Native 应用中使 ...
- [Redux] Redux: Extracting Container Components -- AddTodo
Code to be refactored: const AddTodo = ({ onAddClick }) => { let input; return ( <div> < ...
- [Redux] redux之combineReducers
combineReducers combineReducer 是将众多的 reducer 合成通过键值映射的对象,并且返回一个 combination 函数传入到 createStore 中 合并后的 ...
- [React] 14 - Redux: Redux Saga
Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga [入门] Ref: 从redux-thun ...
- redux 简介
概述 Redux 本身是个极其简单的状态管理框架, 它的简单体现在概念少, 流程明确. 但是, 正是因为简单, 使用上没有强制的约束, 所以如果用不好, 反而会让状态管理更加混乱. 我觉得, 用好 R ...
随机推荐
- scrum冲刺
小组第一次冲刺任务及其完成情况描述: 这次主要是先构建一个框架,然后就是完成首页的一些代码编写,能够基本实现首页的注册.登陆以及一些之后完成的内部构建. 在第一次冲刺任务中的收获和体会,以后如何改进的 ...
- npm: 权限阻止修复
在使用 npm install 时,总提示: Error: EACCES: permission denied 今天通过这个命令设置了权限解决了问题: sudo chown -R $(whoami) ...
- Key Technologies Primer 读书笔记,翻译 --- Struct 学习 1
原文链接:https://struts.apache.org/primer.html 本来想写成读书笔记的,结果还是变成翻译,谨作记录,学习. 1.HTML -- 见我前面文章 2.Interne ...
- 我的C++ 学习心得
创建这个博客已经是我大一下学期的暑假了,这一年里,我学习了人生第一门编程语言C++ . C++是一门当前仍然活跃于开发前沿的编程语言.在还未开始正式学习它时,早就听到我们的学长抱怨C++难学.起初,我 ...
- [转]Kaldi语音识别
转:http://ftli.farbox.com/post/kaldizhong-wen-shi-bie Kaldi语音识别 1.声学建模单元的选择 1.1对声学建模单元加入位置信息 2.输入特征 3 ...
- 王垠的40行代码,究竟diao在哪里
王垠是谁? 不用我说了吧!!! 别傻谈,亮码瞧! ;; A simple CPS transformer which does proper tail-call and does not;; dupl ...
- webpack严格模式!!!忽略
1. babel5 babel: { options: { blacklist: ["useStrict"], // ... }, // ... } 2. babel6 修改.ba ...
- JavaPoet开源项目的使用
一.介绍 JavaPoet项目可以动态的生成Java文件,这是一个很强大和很动态的方法,使用注解的时候假如需要生成新的Java文件就可以通过这个开源项目实现. 项目地址:https://github. ...
- 吴恩达机器学习笔记23-神经网络:表述--非线性假设(Non-linear Hypotheses)
我们之前学的,无论是线性回归还是逻辑回归都有这样一个缺点,即:当特征太多时,计算的负荷会非常大.下面是一个例子: 当我们使用
- Matplotlib 使用 - 《Python 数据科学手册》学习笔记
一.引入 import matplotlib as mpl import matplotlib.pyplot as plt 二.配置 1.画图接口 Matplotlib 有两种画图接口: (1)一个是 ...