[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 ...
随机推荐
- mongodb聚合操作
1. mongodb的聚合是什么 聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组.过滤等功能,然后经过一系列的处理 ...
- api controller 接口接收json字符串参数
{"data":{"alarmRepeatTimes":2,"currentMode":1,"moduleResetTimeout ...
- Java实现zip压缩文件的解压
需求描述: 前段时间写了一篇博客<Java实现对文本文件MD5加密并ftp传送到远程主机目录>,实现了一部分的业务需求.然而有些业务可能不止传送一个文件,有时候客户需要传多个文件,原有系统 ...
- Activiti工作流数据库表详细介绍
Activiti的后台是有数据库的支持,所有的表都以ACT_开头. 第二部分是表示表的用途的两个字母标识. 用途也和服务的API对应. ACT_RE_*: 'RE'表示repository. 这个前缀 ...
- JS求数组差集的几种方法
第一种:如果不考虑IE8的兼容性完全可以使用Foreach ,此方法求出arr1 减去 arr2的差集, arr1 = [1,2,3,4];arr2 = [1,2,3]; var subSet = f ...
- 两个VirtualBox版本装的语言不一样?
两个VirtualBox版本装的语言不一样? 1.这个是我用的两个版本的VirtualBox. 2.用这个 VirtualBox-4.3.20-96997-Win.exe安装的时候,一直是英文. 3. ...
- python基础自学 第三天
变量的命名 01.标识符和关键字 标识符 标识符就是程序员定义的变量名.函数名. 标识符可以由字母,下划线,和数字组成. 不能以数字开头 不能与关键字重名 关键字 就是在python内部已经使用的标识 ...
- qrcode.php
<!doctype html><html><head> <meta charset="UTF-8"/> <meta name= ...
- 河北大学python选修课00次作业
学习python认为挺好玩的一件事.看到很多关于python的东西在网上,看到有这个课,认为只是选修课,别人也可以选,自己想不能被别人落下,别人都会,我不会可不行. 而且认为python是一个很强大的 ...
- MySQL9:索引实战
索引 无论是面试,还是实际工作中,对于一个Java程序员来说,数据库优化是避不开的一个技术点,关于数据库的优化,在性能达不到要求的情况下,我大致给出以下几个方向: (1)优化表结构,对常用字段和非常用 ...