[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 ...
随机推荐
- Normalize.css & Reset
Normalize.css: try to keep the style consistent in every browser. Reset: clear style in every browse ...
- 2019/3/7 Java学习之多线程(基础)
Java学习之多线程 讲到线程,就必须要懂得进程,进程是相当于一个程序的开始到结束,而线程是依赖于进程的,没有进程,就没有线程.线程也分主线程和子线程,当在主线程开启子线程时,主线程结束,而子线程还可 ...
- IDEA的Database管理台如何显示
1.找出database的显示view 2.点击设置数据库,下载驱动文件,直接点击下载就行了,用什么数据库就下什么 3.填写服务器地址和用户名密码,点击测试,成功就表示连上了 4.一些常用按钮 5.目 ...
- Maven package 报错解决记录以及编译scala的pom.xml
可以打包的pom.xml: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:/ ...
- 解析.NET对象的跨应用程序域访问(上篇)
在目前的项目开发中,分布式开发已经逐渐成为主流.一个项目要是没有采用分布式架构,都不好意思跟别人说这是一个完整的项目.这句话虽然有些过激,但是随着人们对效率的要求在提高,以及产品需要提升用户体验.只有 ...
- Linux 比较判断运算(if else)
200 ? "200px" : this.width)!important;} --> 介绍 本篇文章主要是列举在shell命令中常出现的一些用来做比较的运算符,这些运算符是 ...
- Python psutil模块使用
import psutil # 获取内存信息 mem = psutil.virtual_memory() total = mem.total / 1024 / 1024 / 1024 used = m ...
- Javascript高级编程学习笔记(32)—— 客户端检测(1)能力检测
能力检测 浏览器厂商虽然在实现公共接口方面投入了大量的精力 但是每种浏览器仍旧存在许多差异 为了让网页能跨浏览器的运行,对浏览器差异做的兼容处理自然无法避免 其中最常用的也就是我们现在所说的能力检测 ...
- JavaScript变量与数据类型详解
变量 变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念.变量可以通过变量名访问. 变量的作用就是用于存储值. 语法: 声明变量时,总是以关键字var打头.任何情况下都应该这样做.然后给变 ...
- 第45节:Java当中的变量,面向对象
Java当中的变量 01 Java当中的实例变量和类变量 什么是实例变量和类变量呢? 实例变量为没有用static修饰符修饰的变量,而类变量为用static修饰符修饰的变量. public class ...