IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> redux 及 react-redux的详细使用过程和案例 。分享搬砖知识的一天,期间打瞌睡了几次。啊哈哈~ -> 正文阅读

[JavaScript知识库]redux 及 react-redux的详细使用过程和案例 。分享搬砖知识的一天,期间打瞌睡了几次。啊哈哈~

搬砖搬砖,分享点搬砖技巧。
第六章了,差不多结束了 ,还有些零零散散的,慢慢搬吧。
之前的章节内容可点这~

第六章 — redux

redux中文官网

6.1 什么是 redux

官方是这样子说的 :reduxJavaScript 应用程序可预测状态容器 ,它可以帮助您编写行为一致、在不同环境(客户端、服务器和本机)中运行且易于测试的应用程序。

官方的解释有时候总是看不懂的

说一下我的理解。

JavaScript 应用程序 : redux 和 react 可是两回事,只是长的像而已。 redux 可以在任何应用程序使用。

redux 有一个核心的东西 ,就是 store . 那现在有了一个新的问题,什么是 store 。

store 英文的释义是商店。在 redux 里它是一个存储数据的地方,就相当于一个容器,一个仓库。整个程序只有一个 store这便于状态的集中管理。

为什么说是可预测呢?

因为 redux 管理的数据的修改过程是我们设置的,也就是我们已经告诉他应该怎么做。并且每次修改之前是会接收到之前的状态。过程是可预测,可跟踪的。

6.2 为什么需要 redux

当程序的功能比较复杂,组件较多,并且需要共享状态共享状态困难时, 使用redux 是一个较好的解决方案。

我们可以通过这两张图理解:有 A , B ,C ,D, 四个房子(组件) ,它们总是会相互借东西。相互交流。(组件交互,状态共享,修改数据)。那么以我们之前的方法,像通过共同的父组件来传递数据,那么父组件会变得很臃肿,因为需要定义一些它本身不需要的状态和方法,只是为了方便儿子们交流。

或者使用消息订阅-发布机制。 B 需要 A的某个数据,就需要订阅,然后 A 发布 。然后 D也需要,于是 D 也需要订阅。个组件来来往往就像如图一样乱七八糟。

在这里插入图片描述

而使用 redux . 就相当于建了一个仓库 , 各房子把需要共享的东西放在仓库,谁需要谁去拿。那么不但把数据需要共享的资源统一一个地方存储,并且方便了其他组件去使用。

在这里插入图片描述

非必要,不使用 redux

并不是如何程序或者 使用了 react 就需要使用 redux 的 。

有句话这样子说

“如果你不知道是否需要 Redux,那就是不需要它。”

为什么呢 , redux 是便于组件共享状态的,如果组件组件交互少,需要共享的状态不多,且不需要 redux 便能解决的那么根本就不需要使用 redux 。

使用场景

  • 组件间需要共享状态,交互较多
  • 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  • 多个用户之间可以协作
  • 与服务器大量交互,或者使用了WebSocket
  • View要从多个来源获取数据

6.3redux 的工作流程图解

在介绍如何使用之前,先了解一下redux 的工作流程是很有必要的,这有助于理解。
在这里插入图片描述

Component 便是组件了

ActionCreators redux 分为 3个部分,核心部分是 Store , 然后是 ActionCreators 和 Reducers.

其中ActionCreators 是创建 action 的 。也就是创建行为的一个模块。

Reducers 处理 dispatch 发出的行为 。也就是实际做出行动的模块。

Store 便是保存状态的核心部分 无论是发出行为,存储数据,还是把结果反应出去都是通过它。

我们可以理解为 redux 就是一个饭店 ,各组件是客人,客人通过 服务员 ( ActionCreators) 下单 ,告诉需要什么菜。于是服务员跟老板说了(Store) , 然后老板让厨师(Reducers) 做菜。最后客人从老板这儿了拿菜。这当然与实际有些不同,但这不妨碍我们更好理解这个过程。

回到实际, 组件在需要发出行为时,调用了 store上的 dispatch 方法 ,途中向 ActionCreators 拿了一下 action。并作为 dispatch 的参数传给 store 。 也就是实际上调用 dispatch方法 的是 组件。

然后Store 把 当前的状态的 action 传给 reducer 。 reducer 处理完后返回新的 状态 给 store。组件再通过 store 的 getState() 方法拿到新的状态数据。

6.4 redux 的使用

安装及基础准备

通过 npm

npm install redux

通过 yarn

yarn add redux

创建相关文件夹和文件

创建组件和 redux 文件夹及 redux 内相关文件(如图所示)

在这里插入图片描述

因为 不同组件有不同的行为,因此可以把不同的 创建action 的文件放在一个文件夹里。如图中的 actions文件夹。

同理 不同组件发出行为的操作也不同 ,也需要不同的 reducer , 因此放在同一个文件夹下。

而 store 仅有一个,因此直接放于 redux文件夹下即可。

constant.js 文件, 用于存储 type 常量,因为 type 的值是我们事先给定的,通过不同 type 触发不同的操作。因此在组件和 reducer 里都需要使用到 type 的值。使用常量,是便于修改,放在打错字。

基本使用

假设我们需要完成一个例子
在这里插入图片描述

将结果的数据存放在 state 中 , 点击 + 或 - 可以对数据进行加一或者减一。结果默认显示 99 。

action

创建 action 的文件不需要引入什么 API ,我们需要创建相关方法,该方法返回通过 action

action 是一个对象, 包括两个属性 typedata , 分别是类型和数据, type 会表明到时候 reducer 应该执行的操作, data 是传递的数据。此数据来源组件。也就是 action 文件暴露的方法是给组件调用的,并且组件会传入一个数据。

// 分别暴露 创建的相应的创建 action 的方法 ,当其他地方需要使用action时,调用这个方法便创建并可以返回 action。
export let createIncrease = (data) => ({ type: “increase”, data })   
export let createDecrease = (data) => ({ type: ”decrease“, data })
reducer

reducer文件 也是不需要引入什么 API 的。它用来创建为某组件专门服务的 reducer 函数仅一个,判断 type 提供不同的操作。

reducer 函数接收两个参数 , 第一个是 preState , 其实是当前的状态(因为经过此次操作后,会返回新的 State ,因此把它叫做 preState, 含义是之前的状态),第二个参数是 action 。

reducer 会在 redux 加载后执行一次,此次会返回一个默认值。

/*
 1. 此文件用来创建一个为 Count 组件的 服务的 reducer . 本质是一个函数
 2. 函数接收两个参数 , 第一个是之前的 preState , 第二个是动作对象 action (包括行为,和数据)
*/
export default function countReducer(preState, action) {
    console.log(preState);
    console.log(action);
    const { type, data } = action
    switch (type) {
        case "increase":
            return preState + data
        case "decrease":
            return preState - data
        default:
            return 99  // 初始返回的默认值
    }
}

注意:

  • preState 如果是原始值可以修改本身,再返回本身,如果是引用值切记不能修改本身然后返回本身 因为 redux 会对返回值与 preState 进行地址比较,如果是一样的地址会导致更新的失败。
// 如果是原始值,如此操作不影响结果
case "increase" :  
	preState += data 
	return preState

// 如果是引用值 ,以下操作是错误的
case "pop" :{
    preState.pop()
    return preState
}
  • reducer 要求必须是一个纯函数。但如果不存并不会报错。存函数需要满足以下几点操作
1. 不得修改参数 (即使是原数组,也尽量不要修改)
2. 不应该具有其他副功能,如果发送网络请求,连接到其他输入输出设备
3. 不能使用不存的函数,如 Date.now() , Math.random() 等返回值不确定不唯一的 API。
store

store文件 是 redux 的核心。

创建 store 需要从 redux 引入 createStore API 。 它是一个函数。此函数返回一个 Store。

createStore 函数可以接收三个参数。

第一个参数是 reducer(必须) 。 或者是 reducers (多个 reducer 的合并,接下来会讲)。

第二个参数是 初始状态(非必须) 。 如果这个参数没有给,那么第三个参数就成为了第二个参数。

第三个参是 支持异步 action 用的( 非必须,接下来会讲) 。如果没有第二参数,那么这个参数是第二参数。

import { createStore } from 'redux'

// 引入为 Count 专门服务的 reducer
import CountReducer from './reducers/count'
// 暴露 state
export default createStore(CountReducer)

如此 redux 的创建和基本代码便完成了

接下来学习 store 的几个 API 和使用 store

store.dispatch(action)

这是发出 action 的唯一方法 , 组件拿到action , 拿到 store . 便可调用 dispatch 方法,传递 action 给 store

/**  Count Component  **/

// 导入 store
import store from '../../redux/store'
// 导入创建 action 的函数
import { createIncrease } from '../../redux/actions/count' 

	// 组件实例的方法
    incread = () => {
        store.dispatch(
            createIncrease(1)
        )
    }
    
// 当 action 比较少时, 我们也可以不需要 action函数 。
        store.dispatch(
            {
                type:"increase",
                data:1
            }
        )
store.getState()

store.getState() 是获取 store 当前数据的一个 API 。也就是获取 reducer 最后一次的返回值。

// 导入 store
import store from '../../redux/store'

// 组件内
render(){
    return (<h1>结果为 :{store.getState()}</h1>)   // 结果为 : 99
}
store.subscribe()

我们知道当组件的 state 改变时,会重新渲染组件 。 但无论是 store 还是 reducer 都不会把改完后的数据主动给组件,或者告诉组件一个更新了。因此 store 提供了 subscribe API , 当 store 刷新时,会执行这个 subscribe 函数 , 调用传给 subscribe 的回调函数。

因此利用这个API ,我们可以在 store 改变时,刷新 组件即可

/** scr/index.js  **/

import React from "react";
import ReactDOM from "react-dom";
import App from './App';
// 导入 stre
import store from './redux/store'

ReactDOM.render(< App />, document.querySelector("#root"));

// 当 store 刷新时,重新渲染组件,便重新调用 getState 从而获取新的状态。
store.subscribe(() => {
    ReactDOM.render(< App />, document.querySelector("#root"));
})
// 如此全部组件都可以获取新的 store 数据了
完成例子 - 加减计算器

redux 相关文件和代码在上面的介绍中已经完成。接下来我们看看完整的组件代码。注意 scr/index.js内需要使用 subscribe API

import React, { Component } from 'react'
// 导入 store
import store from '../../redux/store'
// 导入 action
import { createIncrease, createDecrease } from '../../redux/actions/count'

export default class Count extends Component {
    incread = () => {
        store.dispatch( createIncrease(1))
    }
    decread = () => {
        store.dispatch(createDecrease( 1))
    }
    
    render() {
        return (
            <div>
                {/* 显示结果 */}
                <h1>结果为 :{store.getState()}</h1>&nbsp;
                {/* 点击加一 */}
                <button className="btn btn-default" onClick={this.incread} >+</button>&nbsp;&nbsp;
                {/* 点击减一 */}
                <button className="btn btn-default" onClick={this.decread} >-</button>
            </div >
        )
    }
}

数据共享

在这里插入图片描述

redux 的主要目的就是多状态数据共享。所以这个功能是很重要的。

在前面的基本使用我们只创建一个了 reducer。 然后把该 reducer 作为 createStore() 的第一个参数 。那如果我们使用 redux 几乎不会只有一个 reducer 的。那么多个reducer 又怎么集合到一个 store 里,组件并且如何获取数据呢?这就是接下来要讨论的问题。

combineReducers

这是 redux 暴露的一个 API 。它用来把所有的 reducer 集合一起返回值然后作为第一参数传给 createStore ()。 那么不同组件的 数据就可以集中保存到 store 中,需要就可以向 store 拿便可

// 额外导入 combineReducers
import { createStore ,combineReducers} from 'redux'


// 引入 Count 的 reducer
import CountR from './reducers/countR'

// 引入 其他 reducer
import OtherR from './reducers/otherR'

// 调用 combineReducers ,传入对象。返回作为 createStore的第一个参数
const allReducer = combineReducers({
    data1:CountR,   // 为方便解释,实际可不能这么顺便
    data2:OtherR
})
// 创建store
export default createStore(allReducer)

除了增加一个 reducer 外,其他代码并不需要修改上面(同基本使用一样)

然后便是如何获取数据了

虽然 store 保存了多个状态了,但获取数据还是通过 store.getState() 来获取。

当只有一个 reducer 时store.getState() 的返回值就是 该 reducer 处理完后 return 的 newState

当有多个 reducer 时 , store.getState() 返回的是一个对象 ,可以理解为就是传给 combineReducers的对象,不过键对于的值是每次执行对应的 reducer 后的返回值 。

// 如果 combineReducers 的参数是如此的

// const allReducer = combineReducers({
//    data1:CountR,   // 为方便解释,实际可不能这么顺便
//    data2:OtherR
// })

// 在组件里获取相应 reducer 返回的状态就是
store.getState().key
// 如 获取 Count 的 reducer 返回的状态
store.getState().data1

异步 action

在上面的例子中, action 都是同步的,也就是点击加一后结果立即加一,如果有一个异步操作,比方说发个请求,或者倒计时几秒后再执行应该怎么如何操作呢?

假设我们有这样的一个需求,我们希望以上例子的基础上加一个按钮,点击后3 秒再增1.

在这里插入图片描述

如果把异步操作放在 视图容器可就是组件里,那么异步加确实是很方便操作。

Asyncdecread = () => {
        setTimeout(() => {
        store.dispatch(
            createIncrease(1)
        )
    }, 3000);
}

但是我们是希望 组件是显示状态的 , 如果这种异步操作少,那么确实把异步放组件里很方便,也容易修改。

但一旦异步操作多了起来,数据处理更复杂了,那么组件就不该承当这些功能了。

Store 当然也不能做到异步操作, reducer 是纯函数,只执行 State 的修改。那么实现异步 action 的任务还是归给了 action Creators

applyMiddleware

我尝试了在 action 里直接写异步操作

setTimeout(() => {
    return { type: "increase", 1 }
}, 3000);

点击加一后执行结果报错。 报错信息说 action Creators 返回的应该一个是一个对象,而不是 undefined

为什么呢?不是 3 秒后返回 一个对象了吗? 这就跟 JavaScript 的异步函数执行机制有关了。这说下去篇幅就大了。

总之呢就是不行。

为了实现异步 action , 我们需要 使用一个 东西, 叫 applyMiddleware

applyMiddleware 是一个函数 , 它可以对 store.dispatch() 进行改造 。 让我们在执行 dispatch() 之后并且 在执行 reducer 之前能够执行其他操作,如异步操作。

applyMiddleware 是 redux 提供了一个 API 。 可作为 createStore()的 第二或 第三 个参数传入 。

export default createStore(reducer, applyMiddleware())

我们知道 action Creators 如果执行异步操作后再返回 action 是无法被 store.dispatch 接收的 。 因此我们可以把思路转到,执行异步操作后再执行 dispatch()

applyMiddleware 便支持我们这样做 。

// 组件
store.dispatch(createIncreaseaAsync(1, 3000))   // 表示 3 秒后加一

// action Creator 
export let createIncreaseaAsync = (data, delay) => {
    return (dispatch) => {
        setTimeout(() => {
            dispatch({type:"increase",data:data})
        }, delay);
    }
}

这里我们直接返回一个函数,在函数内部执行异步操作。结束后再次发送 dispatch 。 而这个 dispacth方法等同于 store.dispatch方法 。 它是 applyMiddleware 传进来的 。

如此我们便解决了异步的问题了 。但这又有一个问题,就是 action Creators 要求返回的是对象,可不是函数。

因此我们需要使用 一个 中间件 。叫 redux-thunk

redux-thunk

redux-thunk 是一种中间件 , 它可以让 action Creators 返回函数,并且让 dispatch() 可以接受函数参数。

中间件 - middleware , 它的使用方法就是作为 applyMiddleware 的参数。

使用过程

  • 安装

yarn add redux-thunk

或者

npm install redux-thunk

  • 导入

import thunk from ‘redux-thunk’

  • 使用

export default createStore(allReducer, applyMiddleware(thunk))

如此我们便可顺利执行 异步 action 了 。

异步action 实现代码

store.js

// 额外导入 applyMiddleware
import { createStore, applyMiddleware} from 'redux'
// 导入 thunk
import thunk from 'redux-thunk';
// 引入 Count 的 reducer
import reducer from './reducers/count'

export default createStore(reducer, applyMiddleware(thunk))

action Creators

// 暴露创建action 加 减 的方法 
export let createIncrease = (data) => ({ type: 'increase', data })
export let createDecrease = (data) => ({ type: 'decrease', data })

// 导出异步的 actiob.
export let createIncreaseaAsync = (data, delay) => {  // 接收两个参数,数据和计时器倒计时长
    // 返回函数
    return (dispatch) => {  // 函数接收到一个 dispatch 方法
        setTimeout(() => {
            dispatch(createIncrease(data))  // 异步操作结束后 重新 dispatch 发生 action 
        }, delay); 
    }
}

reducer

参考 redux 的基本使用 的 reducer 部分代码。

Count-component 注意 要使用 store.subscribe() 在改变状态时重新渲染组件

import React, { Component } from 'react'
// 导入 store
import store from '../../redux/store'
// 导入 action 和异步 action 
import { createIncrease, createDecrease, createIncreaseaAsync} from '../../redux/actions/count'

export default class Count extends Component {
    incread = () => {
        store.dispatch( createIncrease(1))
    }
    decread = () => {
        store.dispatch(createDecrease(1))
    }
    // 异步 action 
    increadAsync= ()=>{
        store.dispatch(createDecrease(1,3000))
    }
    render() {
        return (
            <div>
                {/* 显示结果 */}
                <h1>结果为 :{store.getState()}</h1>&nbsp;
                {/* 点击加一 */}
                <button className="btn btn-default" onClick={this.incread} >+</button>&nbsp;&nbsp;
                {/* 点击减一 */}
                <button className="btn btn-default" onClick={this.decread} >-</button>&nbsp;&nbsp;
                {/* 点击异步加一 */}
                <button className="btn btn-default" onClick={this.increadAsync} >异步执行</button>
            </div >
        )
    }
}

6.5 react-redux

react-redux 便是 react 官方出的了 。 它的作用是让 react 使用 redux 更加方便 。

但并不是必须要使用,因为需要学习成本,本身代码量也可能会增加。并且有新的使用规则。

为什么使用 react-redux

  • 它区分了 UI 组件和 容器组件,进一步区别开逻辑和 UI 。
  • 它提供的效率,减少不必要的重新渲染。部分未更新的 State 不会导致 组件的重新渲染。
  • 它自动监听 state 变化,自动刷新组件 。

react-redux 工作原理图

在使用前我们还是先看看它的 工作原理图。便于接下来的学习。

在这里插入图片描述

在之前 , redux 和 组件是直接联系的 。 组件需要数据直接 store.getState() 也就是直接 store.dispatch()

react-redux 把组件分成了 容器组件UI 组件 。 redux 的书写无需更改。

容器组件把 UI 组件需要的 状态和 创建 action 的函数 通过 props 传递给 UI 组件 。 UI 组件负责显示和 执行 函数修改状态 。 但 UI 组件不会 引入 store 和 创建action的方法 。 这些逻辑的实现全都有 容器组件负责

说白了 UI 组件就是 给数据我显示 ,给方法我执行 。 什么怎么来 , 方法的具体实现我都不管。

这里具体看看 两个组件的要求 :

UI组件
  • 只负责 UI 的呈现,不带有任何业务逻辑
  • 状态和操作状态的方法由容器组件提供
  • 不使用任何 Redux 的 API
容器组件
  • 负责管理数据和业务逻辑,不负责 UI 的呈现
  • 带有内部状态
  • 使用 Redux 的 API

具体实现

安装

yarn add react-redux

或者

npm install react-redux

创建组件

因为 react-redux 把组件分为了 容器组件和 UI 组件 。因此我们可以分为两个文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-poVXItUl-1631970048324)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210918181024805.png)]

connect

connect() 是 react-redux 暴露的一个 API 。 它用来连接 容器组件和 UI 组件的 。

此方法需要传递两个函数参数 。并且都是必须参数

第一个参数

mapStateToProps : 字面意思是映射状态到 Props . 它是一个函数,此函数把需要的状态数据取出 ,最后返回一个对象 , 此对象里的键值会被传递到 UI 组件的 props属性 里

此函数会接收到一个参数 。 此参数的数据相当于 store.getState() 返回的数据。

function mapStateToProps(state){  // 由 react-redux 调用。会传入参数 state . 即reducer处理后的状态
    return {
        count:state   //  count 会被传到 UI 组件的 props 里
    }
}

第二个参数

mapDispatchToProps : 意思是 映射 dispatch 到 props 。 它是一个函数 , 此函数返回一个对象。对象的键对应的值是一个函数,此函数执行的是 dispatch 方法。dispatch 是由 react-redux 传进来的参数 。

function mapDispatchToProps(dispatch){   // 传入参数 dispatch
    return {
        fun1:(data)=>{dispatch(createIncrease(data))},  // 此方法会传入到 UI 组件的 Props 里
        fun2:(data)=>{dispatch(createDecrease(data))},
    }
}

因此函数传给 UI 组件,组件调用函数就相当于调用 dispatch了 。

简写

  • 当需要的状态不多,时我们可以把 mapStateToProps 以匿名箭头函数的方式直接作为 connect 的参数。

  • 第二个参数可以直接是一个对象 , 重复的调用 dispatch 可不符合 react-redux 的目的。 因此我们只需要把键对应的值换成 action Creator , 然后 react-redux 会处理好,等组件调用时就相当于调用 dsipacth 了 。

connect(
    state => ({ count: state}),
    {
        fun1: createIncrease   // 参数是正常接收的 。 UI 组件调用 fun1(data) , 此参数会传给 createIncrease函数。
        fun2: createDecrease
    }
 )

connect 返回值

connect 返回一个函数,实际上来说 , 这个返回的函数才是真正创建 容器组件的函数 。

是的,容器组件可不是我们自己写的 。而是 react-redux 创建的 。

connect 返回值的函数接收一个参数 ,此参数是 UI 组件 。 最后的返回值才是容器组件 。

// 引入 UI 组件
import CountUI from '../../component/Count'  // 会在下面的贴出代码
// 获取 创建 容器组件的函数
let containerCreator = connect(mapStateToProps,mapDispatchToProps)
// 创建容器组件
export default containerCreator(CountUI)  // 暴露容器组件

// 简写
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)

容器组件创建好了,就该使用了

在 容器组件中我们没有导入 store 。 store 需要我们在使用容器组件时传给容器组件的 props 。并且键就叫 store.

import React, { Component } from 'react'
// 导入容器组件
import Count from './container/Count'
// 导入 store
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>
        <Count store={store} />
      </div >
    )
  }
}

因为容器组件的子组件是 UI 组件,因此我们只需要把 容器组件渲染出去, UI 组件自然就显示出来了 。

Provider

Provider 是 react-redux 暴露的一个组件 。此组件没有什么其他功能,也不负责渲染 UI 。 它只做一件事,就是把 store 传给所有的容器组件 。 从而不需要我们使用一个容器组件就自己手动传一次 store 。

一般我们在 scr 下的入口文件 即 index.js 文件里使用 , 如此可以覆盖使用的 容器组件。

import React from "react";
import ReactDOM from "react-dom";
import App from './App';

// 导入 store
import store from './redux/store'

// 导入入 react-redux 提供 Provider 组件
import { Provider } from 'react-redux'

ReactDOM.render(
<Provider store={store} >
    < App />
</Provider>, 
document.querySelector("#root"));

如果还记得之前的 store.subscribe() 就会发现, 这里我们没有使用它了。因为 react-redux 会帮我们监听 store 里状态的改变 ,并且自动更新。

具体代码

container/Count.js

// 引入 UI 组件
import CountUI from '../../component/Count'

// 引入 connect 连接 UI 和 reudx
import { connect } from 'react-redux'

// 引入 action
import {createIncrease,createDecrease,createIncreaseaAsync} from '../../redux/actions/count'

// 第二个参数简便的写法
const mapDispatchToProps={
    fun1:createIncrease,
    fun2:createDecrease,
    fun3:createIncreaseaAsync
}


// 调用 connect 函数,返回一个函数 , 再调用返回的函数。返回一个container组件 .此组件连接UI组件和redux
export default  connect(
    state=>({count:state}),
    mapDispatchToProps)(CountUI) // 连接 UI组件

component/Count.jsx

import React, { Component } from 'react'
// 不可引入 store

export default class Count extends Component {
    incread = () => {
        // 调用 方法
        this.props.fun1(1)

    }
    decread = () => {
        this.props.fun2(1)
    }
    increadAsync = () => {
        this.props.fun3(1,3000)
    }
    render() {
        return (
            <div>          {/** 获取状态 **/}
                <h1>结果为 :{this.props.count}</h1>&nbsp;
                <button className="btn btn-default" onClick={this.incread} >+</button>&nbsp;
                <button className="btn btn-default" onClick={this.decread} >-</button>&nbsp;
                <button className="btn btn-default" onClick={this.increadAsync} >异步加油</button>&nbsp;
            </div >
        )
    }
}

redux相关文件不变

在 App.jsx 里使用 Count的容器组件 , 在 index.js 里使用 Provide组价 并且 传入 store 即可

参考
redux概念之一:redux简介
阮一峰的 redux 教程
尚硅谷react教程 redux部分

一万 3千字,真干到流泪啊~ 。
阮一峰的教程和尚硅谷的教程都讲的很好。我写这些即方便自己以后回顾,也希望能帮助需要学习的人。
redux 自己出了一个开发者工具,可以检测,测试,回顾 state 的状态 。很好用。
对这个的使用我就不解释了 。尚硅谷的课程有讲,看一看视频便可

redux开发者工具的使用
如果你的谷歌游览器访问不了外网,那么可以在这个网站里下载插件
crx4下载redux devtools

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:54:08  更:2021-09-19 07:54:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:38:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码