react-redux状态管理,类似于vuex,这个是在redux中非常重要的一点!

redux是js的状态容器,和vuex差不多

redux可以构建,一致性的应用,原生的可以,而且也可以兼容更多的库jq也可以 原生的js也可以使用
redux很小只有2kb

设计的初衷,数据越来越复杂,嵌套的数据太多,管理不断变化的state非常的麻烦,那么我们就需要一个全局的容器
来管理这些状态,避免混乱

三大核心概述

  1. 单一状态树,

    这一点都和vuex的概念是一样的,整个的页面的state都会存在一颗object tree中,而object tree又存储在 soter中 image.png

  2. state是只读的,

    和vuex中的muation是一毛一样的,只不过变成了另一个名字 action, 改变state的唯一方法是触发一个action,action就是一个普通的对象,所有的修改都会集中处理,并且一个一个的 去执行

如何发送一个acion?非常的简单 和vuex中也差不多 image.png

  1. 使用纯函数,来执行修改

为了描述action如何改变state tree,你需要去编写reducers,
reducers,是一个纯函数而已啦,它接受先前的state和action 返回新的state,
它可以复用,控制顺序,传入辅助参数

redux的核心组成

State-状态

这个就是我们传入的数据,我们在做react的时候,大概可以分三类state

image.png

Action-事件

这个实际上action就是一个对象,它是一个载体 image.png

特点如下:
注意啊,action是描述,表示将要有什么改变
image.png

reducer

这个东西也算是一个函数,响应传递过来的actions,然后处理它,最终把处理好的state发送会store
image.png

Store核心

image.png

小结

image.png

示例小demo

首先是起项目

一个非常简单的基于reatc-creat-cli的小项目需要启动出来,让后初始化删除一些没有用的东西,配置一下我们的目录,下载redux就好了

  1. 重点说明:我们需要删除那些不需要的文件呢?

我们只需要保留如下的文件就好了
image.png其它的初始化的时候一些没有用的都可以删除掉

最后就是你需要安装redux就好了

大概的步骤如下

image.png
image.png
image.png

代码层级如下

image.png

  • 核心代码如下

/action

  1. /**
  2. * action 构建函数
  3. */
  4. const sendAction = () => {
  5. return {
  6. type: 'SEND_TYPE',
  7. valu: '我是一个action'
  8. }
  9. }
  10. export { sendAction }

/reducer

  1. /**
  2. * 本文件用来创建reducer函数来处理传递过来的acstion
  3. */
  4. const initState = {
  5. value: '默认的值'
  6. }
  7. const reducer = (state = initState, action) => {
  8. switch (action.type) {
  9. case value:
  10. return Object.assign({}, state, action)
  11. default:
  12. return state
  13. }
  14. }
  15. export { reducer }

/store

  1. import { createStore } from 'redux'
  2. import { reducer } from '../reducer/index'
  3. /**
  4. * 构建 传入参数,构建store
  5. */
  6. const store = createStore(reducer)
  7. export { store }

/page

  1. import React from 'react'
  2. import { sendAction } from '../action';
  3. import { store } from '../store';
  4. class Home extends React.Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {}
  8. }
  9. handClick = () => {
  10. const action = sendAction()
  11. // 发送action
  12. store.dispatch(action)
  13. }
  14. // 监听
  15. componentDidMount () {
  16. store.subsctibe(() => {
  17. // 注意要触发redner需要重新调用setdata
  18. this.setState({})
  19. })
  20. }
  21. render () {
  22. return (
  23. <>
  24. <button onClick={this.handClick}>点击我,发送一个action</button>
  25. <div>{store.getState().value}</div>
  26. </>
  27. )
  28. }
  29. }
  30. export default Home;

react-redux

在上面的代码我们知道了这样的一个事情:如果我们需要频繁的搞这个redux那么,是非常麻烦的,我们有没有一个东西,可以全局的管理这些storte呢?这个就是我们的react-redux的作用

概述

image.png
image.png
有两个非常重要的东西,需要我们学习,
image.png

  1. provider是什么?它的原理是什么?

image.png

  1. connect

image.png

  1. 总结

image.png

基础的使用

我们需要实现如下的这个小的功能

image.png

首先是前期的准备工作

  1. 首先 下包

    1. npm install react-redux
    2. npm install redux
    3. # 注意啊,我们的react-redux是依赖redux的,所以你需要把redux也下载下来
  2. 其次是构建文件目录

image.png

  1. 然后是写代码(这里的代码及仅仅是我们的reducer还有页面的结构还有我们的stroe)

    这里我们书写了 page两个页面,还有一个人reducer 还有srtore东西

/Com A 和B的组件
image.png
image.png
我们来看一下核心的几个代码

/reducer
image.png
/store
image.png

使用provider来包裹数据

这个是一个组件!!!,它的作用就想之前我们的转态提升的provider东西一样

  • 在我们的provider组件包裹组件结构,达到统一维护store的目的

app.js
image.png
注意啊,这里的这个语法还有proiver接受的参数的固定的语法

有了提供者,我们还需要消费者

这个消费者就是connect,connect放回一个加强之后的组件HOC 注意啊这里的语法,实际上是内部的处理是一个HOC模式,它在HOC封装了一下把全局得我store数据床底到了组件内部的prop上,这种设计就非常的巧妙

  • 参数项说明

image.png
在官方文档上比较难理解,我们在项目中就非常容易的理解了

  • 这个map和vue上的东西也非常的类似
  • 组件A是发送方,需要实现第二个参数

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

  • 我们的B组件需要接受数据,

思路:
image.png

  1. 在我们的redux中初始化值,这个还是非常关键的,初始化值

image.png

  1. 在组件上

细节说明,如果你的connect回自动给你生成第二个参数
image.png

正式的进入逻辑

reudcer,js中才是我们正在的逻辑代码所在
image.png

这个案例中数据的扭转?😋

image.png

非常重要,非常通用的设计模式

image.png自己的个人理解,action是一个载体表示将要做什么,reducer是接受action参数,处理一些数据,数reducer是数据的更改初始化的地方,store是管理实现rudeux和compensation通信的容器

combineReducers

概述和介绍

我们的之前写的代码仅仅是一个reducer,如果项目非常的大,你只有一个reducer完成起来就会非常的麻烦,因此这个东西就出来了,它可以管理多个reducer

image.png

语法是非常的简单

  1. combineReducers是一个函数 返回组合之后的总的大的,reducer
  2. const reducers = {
  3. home:HomeReducer,
  4. login:LoginReducer,
  5. }
  6. exprot combineReducers( reducers )

案例事件到了、

我们将会学习到如下的知识点

image.png

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

案例准备 (没哟使用combineRuducers的时候)

image.png

代码如下 项目的目录结构

image.png
// 注意啊 ,现在我们的一个组件需要
./comA

  1. import React from 'react';
  2. import { connet } from 'react-redux'
  3. class ComA extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. }
  7. handerClick = () => {
  8. this.props.getUser()
  9. }
  10. render () {
  11. return (
  12. <>
  13. <button onClick={handerClick}>点击我获取用户数据</button>
  14. <ul>
  15. <li>姓名:{}</li>
  16. <li>邮箱:{}</li>
  17. </ul>
  18. </>
  19. );
  20. }
  21. }
  22. mapStateToProps = (state) => {
  23. return state
  24. }
  25. mapDispatchToProps = (dispatch) => {
  26. return {
  27. getUser = () => {
  28. dispatch({
  29. type: 'GET_USER'
  30. })
  31. }
  32. }
  33. }
  34. export default connet(mapStateToProps, mapDispatchToProps)(ComA);

/comB是与A类似的,这里就不写了

/sotre/reducers/index

  1. const ininSatte = {}
  2. export function rootReducer (state = ininSatte, action) {
  3. return Object.assign({}, state, action)
  4. }

/sotre/index.js

  1. import { createStore } from 'redux'
  2. import { rootRoducer } from '../store/reducer'
  3. export default createStore(rootRoducer)

/App

app这里非常的简单这里就没有写了,app上直接包裹上一个proders就好了

在rooteRedux中对action进行统一的处理

我们定义了一些数据,在一个reducer里的代码
image.png

对我们的这个rootReducer进行一个改造
image.png

对我们的这个ComA还有ComB进行一个改造
image.png

使用combine进行拆分

image.png

这里只给出了最核心的几个代码

  • 首先是我们的改造的文件夹目录结构

image.png
然后是我们的这个该改造之后的两个子reducer
UserReducer
image.png

另一个也是是一样的
image.png

  • 然后是我们的引入

/store/index.js
image.png

  • 注意啊我们使用的时候也需要经过一般改造

image.png
具体的组件内的使用
image.png

特点说明

image.png
image.png\\第二个特点
image.png

\\第三个特点 重要!
image.png
image.png

综合案例,书城

这个案例业务逻辑稍微有些复杂,但是本质上还是一样的套路 教程的地址:‘https://www.bilibili.com/video/BV1v741127cL?p=10

核心思路如下
image.png
分步骤的案例如下
image.png
image.png

redux-saga(处理异步)

官方API,请自行服用,saga

简介

  1. 中间件

image.png

总结一句哈,我们可以用中间件,拦截一下redux

  1. sage的核心,辅助函数 + effect

image.png

Sage相关的api介绍

这一讲,主要是将的是如何进行与store的关联

/sage/index
image.png

注意啊。一步仅仅是建立了联系,但是在我们的自己建立的sage/index.js下没有什么代码。所以你,就算你在组件发送了dispatch也是不会有什么效果的,因为没有在saga中 监听

saga的辅助函数的说明

以下的是东西 ,是一个简单的saga函数的说明项,官方的文档比较晦涩难懂,我们还是根据代码的来看具体的作用是什么
image.png

组价的触发事件,这个和我们我们之前写的都是一毛一样的,没有什么不同直接发action就好了
image.png

在我们的store/sage/index.js中进行监听,注意啊这里的es6的新特点 yield函数

image.png

三个辅助函数的说明

我们来请求接口,看看具体的区别是什么。这里我们直接写在sage中,进行了一些拦截处理还有辅助函数的使用
image.png
这三个辅助函数的区别是什么?
image.png

Effect函数

image.png

这里有必要说一下take的东西,take就是run的时候就堵塞,匹配到之后就接着进行
image.png

  • 发送action就能发送出去action
  • image.png

reducer中如何接受到了呢?,注意啊这约定俗成,我们的这object.assgina是最约定俗成的方法
image.png

总结
image.png

项目实战

初始化项目准备action, reducer,分模块的saga

学以致用,我们来完成一个项目的实战吧!案例描述,我们来实现一个异步网络请求的在线书城项目 注意啊,这里实际上还有我们的reducer我们还没有写,你需要自己写一下 image.png

我们的aciton类型常量也需要自己设置一下 image.png

这两个reducer中写的东西和我们之前写的东西是一毛一样的,没有任何的变化,我们的变化只是集中在saga文件中拦截做对应的处理

image.png

要点就是同时运行两个saga这个是一个要点
/saga/index.
image.png

/sore/index/js。进行我们的数据管理
image.png

实现登录

  1. 思路的讲解

image.png

  1. 重点说明
  • 登录的saga 处理逻辑

image.png

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

image.png

  • 前台的触发条件

我们的map把redux中的store进行映射到了当前组件的props上,如果有请求就说明prop变了,那么我们就需要在组件的内部进行一定更新处理
image.png
后续的操作就是进行业务的处理,这里就不详细的展开了

书籍的列表数据

思路都是一样的,这里就不展示源代码了 image.png

  1. 组件的加载的时候直接触发钩子函数,发送action请求数据

image.png

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

image.png

  1. 最后你需要put一下把获取到的数据丢出去

image.png4

  1. 在reducer里,进行数据的放回

image.png

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

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