react-redux状态管理,类似于vuex,这个是在redux中非常重要的一点!
redux是js的状态容器,和vuex差不多
redux可以构建,一致性的应用,原生的可以,而且也可以兼容更多的库jq也可以 原生的js也可以使用
redux很小只有2kb
设计的初衷,数据越来越复杂,嵌套的数据太多,管理不断变化的state非常的麻烦,那么我们就需要一个全局的容器
来管理这些状态,避免混乱
三大核心概述
单一状态树,
这一点都和vuex的概念是一样的,整个的页面的state都会存在一颗object tree中,而object tree又存储在 soter中

state是只读的,
和vuex中的muation是一毛一样的,只不过变成了另一个名字 action, 改变state的唯一方法是触发一个action,action就是一个普通的对象,所有的修改都会集中处理,并且一个一个的 去执行
如何发送一个acion?非常的简单 和vuex中也差不多 
- 使用纯函数,来执行修改
为了描述action如何改变state tree,你需要去编写reducers,
reducers,是一个纯函数而已啦,它接受先前的state和action 返回新的state,
它可以复用,控制顺序,传入辅助参数
redux的核心组成
State-状态
这个就是我们传入的数据,我们在做react的时候,大概可以分三类state
Action-事件
这个实际上action就是一个对象,它是一个载体
reducer
这个东西也算是一个函数,响应传递过来的actions,然后处理它,最终把处理好的state发送会store
Store核心

小结

示例小demo
首先是起项目
一个非常简单的基于reatc-creat-cli的小项目需要启动出来,让后初始化删除一些没有用的东西,配置一下我们的目录,下载redux就好了
- 重点说明:我们需要删除那些不需要的文件呢?
我们只需要保留如下的文件就好了
其它的初始化的时候一些没有用的都可以删除掉
大概的步骤如下



代码层级如下

- 核心代码如下
/action
/*** action 构建函数*/const sendAction = () => {return {type: 'SEND_TYPE',valu: '我是一个action'}}export { sendAction }
/reducer
/*** 本文件用来创建reducer函数来处理传递过来的acstion*/const initState = {value: '默认的值'}const reducer = (state = initState, action) => {switch (action.type) {case value:return Object.assign({}, state, action)default:return state}}export { reducer }
/store
import { createStore } from 'redux'import { reducer } from '../reducer/index'/*** 构建 传入参数,构建store*/const store = createStore(reducer)export { store }
/page
import React from 'react'import { sendAction } from '../action';import { store } from '../store';class Home extends React.Component {constructor(props) {super(props);this.state = {}}handClick = () => {const action = sendAction()// 发送actionstore.dispatch(action)}// 监听componentDidMount () {store.subsctibe(() => {// 注意要触发redner需要重新调用setdatathis.setState({})})}render () {return (<><button onClick={this.handClick}>点击我,发送一个action</button><div>{store.getState().value}</div></>)}}export default Home;
react-redux
在上面的代码我们知道了这样的一个事情:如果我们需要频繁的搞这个redux那么,是非常麻烦的,我们有没有一个东西,可以全局的管理这些storte呢?这个就是我们的react-redux的作用
概述


有两个非常重要的东西,需要我们学习,
- provider是什么?它的原理是什么?

- connect

- 总结
基础的使用
我们需要实现如下的这个小的功能

首先是前期的准备工作
首先 下包
npm install react-reduxnpm install redux# 注意啊,我们的react-redux是依赖redux的,所以你需要把redux也下载下来
其次是构建文件目录

- 然后是写代码(这里的代码及仅仅是我们的reducer还有页面的结构还有我们的stroe)
这里我们书写了 page两个页面,还有一个人reducer 还有srtore东西
/Com A 和B的组件

我们来看一下核心的几个代码
/reducer
/store
使用provider来包裹数据
这个是一个组件!!!,它的作用就想之前我们的转态提升的provider东西一样
- 在我们的provider组件包裹组件结构,达到统一维护store的目的
app.js
注意啊,这里的这个语法还有proiver接受的参数的固定的语法
有了提供者,我们还需要消费者
这个消费者就是connect,connect放回一个加强之后的组件HOC 注意啊这里的语法,实际上是内部的处理是一个HOC模式,它在HOC封装了一下把全局得我store数据床底到了组件内部的prop上,这种设计就非常的巧妙
- 参数项说明

在官方文档上比较难理解,我们在项目中就非常容易的理解了
- 这个map和vue上的东西也非常的类似
- 组件A是发送方,需要实现第二个参数
思路:

我们还需要方法去触发它。于是就有了hannClik
重点说明:我们的ruderver第一次进来的时候,我们的react第一次底层上会进行触发的,第二次来的时候会与第一次的值进行比较如果没有变哈,那么react底层上不会执行的,如何解决这个问题呢?你需要使用object.assing( {},state,action ) 就好了,返回新的state,这样就能欺骗react底层了
- 我们的B组件需要接受数据,
思路:
- 在我们的redux中初始化值,这个还是非常关键的,初始化值

- 在组件上
细节说明,如果你的connect回自动给你生成第二个参数
正式的进入逻辑
这个案例中数据的扭转?😋

非常重要,非常通用的设计模式
自己的个人理解,action是一个载体表示将要做什么,reducer是接受action参数,处理一些数据,数reducer是数据的更改初始化的地方,store是管理实现rudeux和compensation通信的容器
combineReducers
概述和介绍
我们的之前写的代码仅仅是一个reducer,如果项目非常的大,你只有一个reducer完成起来就会非常的麻烦,因此这个东西就出来了,它可以管理多个reducer

语法是非常的简单
combineReducers是一个函数 返回组合之后的总的大的,reducerconst reducers = {home:HomeReducer,login:LoginReducer,}exprot combineReducers( reducers )
案例事件到了、
我们将会学习到如下的知识点

我们需要完成这样的一个需求
由两个组件,这两个组件有各自的按钮,点击的时候,可以通过redux获取到各自对应reducer的数据,而不是一个reducer数据,现在我们希望使用combineRuducers来改造它
案例准备 (没哟使用combineRuducers的时候)

代码如下 项目的目录结构

// 注意啊 ,现在我们的一个组件需要
./comA
import React from 'react';import { connet } from 'react-redux'class ComA extends React.Component {constructor(props) {super(props);}handerClick = () => {this.props.getUser()}render () {return (<><button onClick={handerClick}>点击我获取用户数据</button><ul><li>姓名:{}</li><li>邮箱:{}</li></ul></>);}}mapStateToProps = (state) => {return state}mapDispatchToProps = (dispatch) => {return {getUser = () => {dispatch({type: 'GET_USER'})}}}export default connet(mapStateToProps, mapDispatchToProps)(ComA);
/comB是与A类似的,这里就不写了
/sotre/reducers/index
const ininSatte = {}export function rootReducer (state = ininSatte, action) {return Object.assign({}, state, action)}
/sotre/index.js
import { createStore } from 'redux'import { rootRoducer } from '../store/reducer'export default createStore(rootRoducer)
/App
app这里非常的简单这里就没有写了,app上直接包裹上一个proders就好了
在rooteRedux中对action进行统一的处理
我们定义了一些数据,在一个reducer里的代码
对我们的这个rootReducer进行一个改造
对我们的这个ComA还有ComB进行一个改造
使用combine进行拆分

这里只给出了最核心的几个代码
- 首先是我们的改造的文件夹目录结构

然后是我们的这个该改造之后的两个子reducer
UserReducer
另一个也是是一样的
- 然后是我们的引入
/store/index.js
- 注意啊我们使用的时候也需要经过一般改造

具体的组件内的使用
特点说明

\\第二个特点
\\第三个特点 重要!

综合案例,书城
这个案例业务逻辑稍微有些复杂,但是本质上还是一样的套路 教程的地址:‘https://www.bilibili.com/video/BV1v741127cL?p=10
核心思路如下
分步骤的案例如下

redux-saga(处理异步)
官方API,请自行服用,saga
简介
- 中间件

总结一句哈,我们可以用中间件,拦截一下redux
- sage的核心,辅助函数 + effect

Sage相关的api介绍
这一讲,主要是将的是如何进行与store的关联
/sage/index
注意啊。一步仅仅是建立了联系,但是在我们的自己建立的sage/index.js下没有什么代码。所以你,就算你在组件发送了dispatch也是不会有什么效果的,因为没有在saga中 监听
saga的辅助函数的说明
以下的是东西 ,是一个简单的saga函数的说明项,官方的文档比较晦涩难懂,我们还是根据代码的来看具体的作用是什么
组价的触发事件,这个和我们我们之前写的都是一毛一样的,没有什么不同直接发action就好了
在我们的store/sage/index.js中进行监听,注意啊这里的es6的新特点 yield函数
三个辅助函数的说明
我们来请求接口,看看具体的区别是什么。这里我们直接写在sage中,进行了一些拦截处理还有辅助函数的使用
这三个辅助函数的区别是什么?
Effect函数

这里有必要说一下take的东西,take就是run的时候就堵塞,匹配到之后就接着进行
- 发送action就能发送出去action

reducer中如何接受到了呢?,注意啊这约定俗成,我们的这object.assgina是最约定俗成的方法
项目实战
初始化项目准备action, reducer,分模块的saga
学以致用,我们来完成一个项目的实战吧!案例描述,我们来实现一个异步网络请求的在线书城项目 注意啊,这里实际上还有我们的reducer我们还没有写,你需要自己写一下
我们的aciton类型常量也需要自己设置一下
这两个reducer中写的东西和我们之前写的东西是一毛一样的,没有任何的变化,我们的变化只是集中在saga文件中拦截做对应的处理
要点就是同时运行两个saga这个是一个要点
/saga/index.
/sore/index/js。进行我们的数据管理
实现登录
- 思路的讲解

- 重点说明
- 登录的saga 处理逻辑

- 登录的rudecer如何拿到数据之后如何处理

- 前台的触发条件
我们的map把redux中的store进行映射到了当前组件的props上,如果有请求就说明prop变了,那么我们就需要在组件的内部进行一定更新处理
后续的操作就是进行业务的处理,这里就不详细的展开了
书籍的列表数据
思路都是一样的,这里就不展示源代码了
- 组件的加载的时候直接触发钩子函数,发送action请求数据

- 在saga中进行监听action,并且请求数据

- 最后你需要put一下把获取到的数据丢出去
4
- 在reducer里,进行数据的放回

- 在相对应的组件页面进行数据处理就好了

注意啊,这里解释一下,为什么这里不需要直接赋值,因为我们在redern函数中,页面第一次的时候就直接解构加载a了





