Redux相关知识(什么是redux、redux的工作原理、redux的核心概念、redux的基本使用)(十一)

news2024/11/25 16:57:17

系列文章目录

第一章:React基础知识(React基本使用、JSX语法、React模块化与组件化)(一)
第二章:React基础知识(组件实例三大核心属性state、props、refs)(二)
第三章:React基础知识(事件处理、受控组件与非受控组件、高阶函数、组件的生命周期)(三)
第四章:React脚手架应用(创建脚手架、代理配置、ajax相关、组件通信)(四)
第五章:react-router5路由相关一(路由相关概念、基本使用、NavLink与NavLink的封装、Switch的使用、严格匹配、路由重定向、路由组件与一般组件的区别)(五)
第六章:react-router5路由相关二(嵌套路由、路由传参、replace、编程式路由导航、withRouter的使用、BrowserRouter与HashRouter的区别)(六)
第七章:React-Router6路由相关一(路由的基本使用、重定向、NavLink·、路由表、嵌套路由)(七)
第八章:React-Router6路由相关二(路由传参、编程式路由导航、路由相关hooks)(八)
第九章:React相关扩展一(setState、lazyLoad、Hooks相关)(九)
第十章:React相关扩展二(Fragment、Content、组件优化、render props、错误边界)(十)


文章目录

  • 系列文章目录
    • 一、什么是Redux
      • 1.1 概念
      • 1.2 何时使用?
      • 1.3 redux的工作原理
    • 二、核心概念
      • 2.1 state
      • 2.2 action
      • 2.3 reducer(重要)
      • 2.4 store
      • 2.5 dispatch
      • 2.6 subscribe(listener)
    • 三、redux的基本使用(搭建redux环境)


一、什么是Redux

1.1 概念

  • Redux 是 JavaScript应用的状态容器,提供可预测的状态管理。可以开发出行为稳定可预测的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。
  • Redux 是一个使用叫做“action”的事件来管理和更新应用状态的模式和工具库,它以集中式Store的方式对整个应用中使用的状态进行集中管理,其规则确保状态只能以可预测的方式更新。
  • Redux提供的模式和工具使您更容易理解应用程序中的状态何时、何地、为什么以及如何更新,以及当这些更改发生时您的应用程序逻辑将如何表现。
  • 类似于vuex 但是不同于vuex,可以对状态进行管理。

1.2 何时使用?

  • 在应用的大量地方,都存在大量的状态
  • 应用状态会随着时间的推移而频繁更新
  • 更新该状态的逻辑可能很复杂
  • 中型和大型代码量的应用,很多人协同开发
  • 不同身份的⽤户有不同的使⽤⽅式(⽐如普通⽤户和管理员)
  • 与服务器⼤量交互,或者使⽤了WebSocket
  • View要从多个来源获取数据
  • 某个组件的状态,需要共享某个状态需要在任何地⽅都可以拿到
  • ⼀个组件需要改变全局状态
  • ⼀个组件需要改变另⼀个组件的状态

1.3 redux的工作原理

在这里插入图片描述
在这里插入图片描述

  • 页面初始渲染时:

    • 使用最顶层的 root reducer 函数创建 Redux store
    • store 调用一次 root reducer,并将返回值保存为它的初始 state
    • 当 UI 首次渲染时,UI 组件访问 Redux store 的当前 state,并使用该数据来决定要呈现的内容。
    • 同时监听store 的更新,以便他们可以知道 state 是否已更改。
  • 页面更新渲染时:

    • dispatch 一个 actionRedux store,例如 dispatch({type:'counter/increment'})
    • store之前的 state当前的 action 再次运行 reducer 函数,并将返回值保存为新的 state
    • store 通知所有订阅过的 UI通知它们 store 发生更新
    • 每个订阅过 store 数据的 UI 组件都会检查它们需要的 state 部分是否被更新。
    • 发现数据被更新的每个组件都强制使用新数据重新渲染,紧接着更新网页

二、核心概念

应用的整体全局状态以对象树的方式存放于单个 store唯一改变状态树的方法创建 action,一个描述发生了什么的对象,并将其 dispatch 给 store。 要指定状态树如何响应 action 来进行更新,你可以编写纯 reducer 函数,这些函数根据旧 state 和 action 来计算新 state

2.1 state

  • 托管给redux管理的状态
  • 示例代码:
let state = { 
	todos:[], 
	params:{} 
}

2.2 action

  • Action

    • Action 描述当前发⽣的事情。改变State的唯⼀办法,就是使⽤Action。它会运送数据到 Store。
    • Action 本质上是 JavaScript 普通对象。action必须使⽤⼀个字符串类型的 type字段表示将要执⾏的动作
    • type 字段是一个字符串,给这个 action 一个描述性的名字,比如"todos/todoAdded"。
    • action对象可以有其他字段,其中包含有关发生的事情的附加信息。按照惯例,我们将该信息放在名为data的字段中,也可放放到其他属性中,不过最好放到data中。
    • 示例代码:
    { type: 'ADD_TODO', text: '去游泳馆' } 
    { type: 'TOGGLE_TODO', index: 1 } 
    { type: 'SET_VISIBILITY_FILTER', filter: 'completed' }
    
  • Action Creator

    • action creator 是一个创建并返回一个 action 对象的函数。它的作用是让你不必每次都手动编写 action对象

    • 示例代码:

    const addTodo = data => ({type: 'todos/todoAdded',data})
    

2.3 reducer(重要)

  • reducer一个函数接收当前的state和一个action 对象,必要时决定如何更新状态,并返回新状态。函数签名是:(state, action) => newState。可以将reducer 视为一个事件监听器,它根据接收到的action(事件)类型处理事件。

  • Reducer 必需符合以下规则:

    • 仅使用 state 和 action 参数计算新的状态值
    • 禁止直接修改 state。必须通过复制现有的 state 并对复制的值进行更改的方式来做不可变更新
    • 禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
  • reducer 函数内部的逻辑通常遵循以下步骤:

    • 检查 reducer 是否联系这个 action
      • 如果是,则复制 state,使用新值更新 state 副本,然后返回新 state
      • 否则,返回原来的 state 不变
  • 示例代码:

    // 初始化状态
    const initialState = { value: 0, index: 1 }
    
    function counterReducer(preState=initialState, action) {
    		//从action对象中获取:type、data
    		const {type,data} = action
    		//根据type决定如何加工数据
    		switch (type) {
    			case 'increment': //如果是加
    				return { 
    					...preState
    					value:preState.value + data
    				}
    			case 'decrement': //若果是减
    				return { 
    					...preState
    					value:preState.value - data
    				}
    			default:
    				// 返回prestate 不变
    				return preState
    		}
    }
    

2.4 store

  • 当前 Redux 应用的状态存在于一个名为 store 的对象中。store 是通过传入一个reducer来创建的,并且有一个getState 的方法,它返回当前状态值

  • Store 就是保存数据的地⽅,可以把它看成⼀个容器。整个应⽤只能有⼀个Store。Redux提供createStore这个函数,⽤来⽣成Store

  • 示例代码:

    //引入createStore,专门用于创建redux中最为核心的store对象
    // 旧版本的引入
    // import {createStore} from 'redux'
    // 新版本的引入
    import { legacy_createStore as createStore } from 'redux'
    //引入为Count组件服务的reducer
    import reducer from './reducer'
    //暴露store
    export default createStore(reducer)
    /* 如果该仓库用多个reducer,则使用combineReducers函数来合并reducer,
       可以通过combineReducers组合多个Reducer,然后通过createStore来创建状态机。*/
    const store2=createStore(combineReducers({
    	 todos,
    	 counter, 
    }));
    

    或者直接使用@reduxjs/toolkit包中的configureStore方法来生成store

    import { configureStore } from '@reduxjs/toolkit'
    const store = configureStore({ reducer})
    

    仓库创建好了之后,将store引入到需要使用仓库的组件中。

    import store from './store/index.js'
    // 分发动作
    store.dispatch({type:'',data:''})
    // 获取仓库数据
    store.getState();
    

2.5 dispatch

  • Redux store 有一个方法叫 dispatch更新 state 的唯一方法调用 store.dispatch() 并传入一个action对象。store 将执行所有reducer函数并计算出更新后的state,调用 getState()
    可以获取新state。

  • 示例代码

    store.dispatch({ type: 'counter/increment' })
    console.log(store.getState())
    // {value: 1}
    
  • dispatch 一个 action 可以形象的理解为 "触发一个事件"。发生了一些事情,我们希望 store
    知道这件事。Reducer 就像事件监听器一样,当它们收到关注的 action 后,它就会更新 state 作为响应。 我们通常调用 action creator 来调用 action

  • 示例代码

    const increment = () => {
     return {
    	 type: 'counter/increment'
     	}
    }
    // 分发动作
    store.dispatch(increment())
    console.log(store.getState())
    

2.6 subscribe(listener)

  • 添加一个变化监听器。每当dispatch action 的时候就会执行,state
    树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state。你可以在变化监听器里面进行
    dispatch(),如果需要解绑这个变化监听器,执行 subscribe 返回的函数即可。

  • 参数listener (Function):当 dispatch action 的时候都会执行的回调。state 树中的一部分可能已经变化。你可以在回调函数里调用 getState() 来拿到当前 state。

  • 返回值(Function): 一个可以解绑变化监听器的函数。

    // 监听方法一
    store.subscribe(() => {
     this.setState({
     ...store.getState()
     });
    }); //订阅者做的事情
    
    // 监听方法二
    store.subscribe(()=>{
    	ReactDOM.render(<App/>,document.getElementById('root'))
    })
    

三、redux的基本使用(搭建redux环境)

  • 安装

    npm install redux
    
  • 主要API

    • createStore(reducer, [preloadedState], [enhancer]) 创建仓库
    • combineReducers(reducers) 合并reducer
    • applyMiddleware(...middlewares) 应用中间件
  • store相关API

    • store.getState() 获取仓库中的状态
    • store.dispatch(action) 分发到某个动作
    • store.subscribe(listener) 订阅仓库内状态更新
    • replaceReducer(nextReducer) 替换reducer
  • 代码案例片段:
    index.js

    import React from 'react'
    import ReactDOM from 'react-dom'
    import App from './App'
    import store from './redux/store'
    
    ReactDOM.render(<App/>,document.getElementById('root'))
    
    store.subscribe(()=>{
    	ReactDOM.render(<App/>,document.getElementById('root'))
    })
    

    App.js

    import React, { Component } from 'react'
    import Count from './components/Count'
    
    export default class App extends Component {
    	render() {
    		return (
    			<div>
    				<Count/>
    			</div>
    		)
    	}
    }
    
    

    redux/count_action.js(该文件专门为Count组件生成action对象)

    //同步action,就是指action的值为Object类型的一般对象
    export const createIncrementAction = data => ({type:'increment',data})
    export const createDecrementAction = data => ({type:'decrement',data})
    
    //异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。
    export const createIncrementAsyncAction = (data,time) => {
    	return (dispatch)=>{
    		setTimeout(()=>{
    			dispatch(createIncrementAction(data))
    		},time)
    	}
    }
    

    redux/count_reducer.js

    /* 
    	1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
    	2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
    */	
    const initState ={value:0 ,index:1} //初始化状态
    export default function countReducer(preState=initState,action){
    	// console.log(preState);
    	//从action对象中获取:type、data
    	const {type,data} = action
    	//根据type决定如何加工数据
    	switch (type) {
    		case 'increment': //如果是加
    			return preState + data
    		case 'decrement': //若果是减
    			return preState - data
    		default:
    			return preState
    	}
    }
    

    redux/store.js

    /* 
    	该文件专门用于暴露一个store对象,整个应用只有一个store对象
    */
    
    //引入createStore,专门用于创建redux中最为核心的store对象
    // 旧版
    // import { createStore } from 'redux'
    //新版
    import { legacy_createStore as createStore, applyMiddleware } from 'redux'
    //引入为Count组件服务的reducer
    import countReducer from './count_reducer'
    //引入redux-thunk,用于支持异步action
    import thunk from 'redux-thunk'
    //暴露store
    export default createStore(countReducer, applyMiddleware(thunk))
    

    components/Count.jsx

    	import React, { Component } from 'react'
    //引入store,用于获取redux中保存状态
    import store from '../../redux/store'
    //引入actionCreator,专门用于创建action对象
    import {
    	createIncrementAction,
    	createDecrementAction,
    	createIncrementAsyncAction
    } from '../../redux/count_action'
    
    export default class Count extends Component {
    
    	state = {carName:'奔驰c63'}
    
    	/* componentDidMount(){
    		//检测redux中状态的变化,只要变化,就调用render
    		store.subscribe(()=>{
    			this.setState({})
    		})
    	} */
    
    	//加法
    	increment = ()=>{
    		const {value} = this.selectNumber
    		store.dispatch(createIncrementAction(value*1))
    	}
    	//减法
    	decrement = ()=>{
    		const {value} = this.selectNumber
    		store.dispatch(createDecrementAction(value*1))
    	}
    	//奇数再加
    	incrementIfOdd = ()=>{
    		const {value} = this.selectNumber
    		const count = store.getState()
    		if(count % 2 !== 0){
    			store.dispatch(createIncrementAction(value*1))
    		}
    	}
    	//异步加
    	incrementAsync = ()=>{
    		const {value} = this.selectNumber
    		// setTimeout(()=>{
    			store.dispatch(createIncrementAsyncAction(value*1,500))
    		// },500)
    	}
    
    	render() {
    		return (
    			<div>
    				<h1>当前求和为:{store.getState()}</h1>
    				<select ref={c => this.selectNumber = c}>
    					<option value="1">1</option>
    					<option value="2">2</option>
    					<option value="3">3</option>
    				</select>&nbsp;
    				<button onClick={this.increment}>+</button>&nbsp;
    				<button onClick={this.decrement}>-</button>&nbsp;
    				<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>&nbsp;
    				<button onClick={this.incrementAsync}>异步加</button>&nbsp;
    			</div>
    		)
    	}
    }
    

    运行结果:
    在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/169183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Arduino 开发ESP8266(ESP12F)模块

①ESP12F模块的硬件说明如上图所示&#xff0c;其他引脚均引出。②准备好硬件之后就是要下载Arduino IDE&#xff0c;目前版本为2.0.3&#xff0c;下载地址为&#xff1a;https://www.arduino.cc/en/software&#xff0c;如下图所示③安装Arduino IDE较为简单&#xff0c;安装之…

aws cloudformation 在堆栈中使用 waitcondition 协调资源创建和相关操作

参考资料 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-waitcondition.htmlhttps://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html 本文介绍cloudformation的waitcondition条件&#xff0c;wait…

Win10之bandicam录音无声音问题

0.问题描述&#xff1a;在Xubuntu22.04中通过gnome-boxes跑win10&#xff0c;但是win10本机录音机录音ok&#xff0c;使用bandicam录屏却没声音的问题&#xff0c;以下是分析步骤。1.Linux端设置选择Xbuntu声音图标speaker选择声卡&#xff1a;sof-hda-dsp Speaker Headphonesm…

DFS剪枝

目录 一、前言 二、剪枝 1、概念 2、类别 三、例题 1、剪格子&#xff08;lanqiaoOJ题号211&#xff09; 2、路径之谜&#xff08;2016年决赛&#xff0c;lanqiaoOJ题号89&#xff09; 3、四阶幻方&#xff08;2015年决赛&#xff0c;lanqiaoOJ题号689&#xff09; 4、…

P1028 [NOIP2001 普及组] 数的计算————C++

题目 [NOIP2001 普及组] 数的计算 题目描述 给出自然数 nnn&#xff0c;要求按如下方式构造数列&#xff1a; 只有一个数字 nnn 的数列是一个合法的数列。在一个合法的数列的末尾加入一个自然数&#xff0c;但是这个自然数不能超过该数列最后一项的一半&#xff0c;可以得到…

linux(debian系列)配置seetaface6

seetaface6依赖于opencv&#xff0c;另外我们需要界面&#xff0c;所以也需要Qt&#xff08;你也可以选择其他的&#xff09;。 这里的目标是配置好环境&#xff0c;能够编译并运行seetaface6给的demo。 那个demo中用到了sqlite数据库&#xff0c;所以我们还需要安装sqlite。…

Cosmos 基础(一)

Cosmos 区块链互联网 Cosmos是一个不断扩展的生态系统&#xff0c;由相互连接的应用程序和服务组成&#xff0c;为去中心化的未来而构建。 Cosmos 应用程序和服务使用IBC(the Inter-Blockchain Communication protocol, 区块链间通信协议)连接。这一创新使您能够在主权国家之…

僵尸进程孤儿进程

目录 1. 僵尸进程 2. 孤儿进程 1. 僵尸进程 僵尸状态&#xff1a;一个进程已经退出&#xff0c;但是还不允许被OS释放&#xff0c;处于一个被检测的状态。 僵死状态&#xff08;Z-Zombies&#xff09;是一个比较特殊的状态。当子进程退出并且父进程没有读取到子进程退出的返…

学习记录663@项目管理之项目范围管理

什么是项目范围管理 项目范围管理包括确保项目做且只做所需的全部工作&#xff0c;以成功完成项目的各个过程。它关注的焦点是:什么是包括在项目之内的&#xff0c;什么是不包括在项目之内的&#xff0c;即为项目工作明确划定边界。通俗地讲&#xff0c;项目范围管理就是要做范…

Dubbo框架学习(第二章Dubbo3拥抱云原生)

由于在微服务领域有两大框架统治&#xff0c;一个是springCloud的全家桶&#xff0c;一个是Dubbo。我用Dubbo比较少&#xff0c;所以也是学习状态。Dubbo框架学习&#xff0c;资料来源于cn.dubbo.apache.org。第二章Dubbo3拥抱云原生新一代的 Triple 协议基于 HTTP/2 作为传输层…

计算机网络第五章、第六章

1.传输层定义&#xff1a;为应用层提供通信服务使用网络层的服务传输层的功能&#xff1a;传输层提供进程和进程之间的逻辑通信复用和分用传输层对收到的报文进行差错检测传输层的两种协议传输层的两个协议&#xff1a;1.面向连接的传输控制协议TCP&#xff1a;传送数据之前必须…

人工智能辅助药物发现(1)肿瘤靶点识别

目录基于AI的靶点识别概述肿瘤建模肿瘤转录组转录组异质性单细胞转录组数据分析单细胞表观肿瘤模型肿瘤中的表观遗传模型基于甲基化测序技术的肿瘤表观遗传模型基于染色质可及性的肿瘤表观遗传模型多模态肿瘤建模靶点识别基于单细胞RNA的靶点发现基于表观的靶点发现基于多组学的…

点击化学交联剂N3-SS-N3,叠氮-二硫键-叠氮简介,CAS:352305-38-5

英文名称&#xff1a;Azidoethyl-SS-ethylazide N3-SS-N3 N3-S-S-N3 化学式&#xff1a;C4H8N6S2 分子量&#xff1a;204.3 CAS&#xff1a;352305-38-5 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于…

《Buildozer打包实战指南》第四节 正式打包一个apk文件

目录 4.1 了解buildozer.spec配置文件中的常用参数 4.2 修改配置文件打包apk 在上一节内容中&#xff0c;我们配置好了打包环境&#xff0c;还顺带成功打包出了一个apk文件&#xff08;读者可以把这个apk安装到手机上运行&#xff09;。不过在打包这个apk前&#xff0c;我们没…

Unity学习笔记--如何在Unity运行cmd?并且在Unity中利用cmd操作svn(例如生成svn--diff文件)

目录前言需求拆分解决方案实操前言 最近工作有一个需求&#xff0c;简单来说是在 Unity 里面动态获取 SVN diff 的数据&#xff0c;并且针对这些 diff 文件做对应操作 需求拆分 我们首先拆分下需求 Unity里面获取 SVN 的 diff 文件针对生成的 diff 文件做解析&#xff0c;找…

Qt 视频播放

一、简介Qt对音视频的播放和控制&#xff0c;相机拍照&#xff0c;收音机等多媒体应用提供了强大的支持。Qt5使用了全新的Qt Multimedia模块来实现多媒体应用&#xff0c;而原来Qt4中用于实现多媒体功能的Phonon模块已经被移除。新的Qt Multimedia模块提供了丰富的接口&#xf…

【从零开始学习深度学习】50.Pytorch_NLP项目实战:卷积神经网络textCNN在文本情感分类的运用

在之前介绍的“卷积神经网络”中我们探究了如何使用二维卷积神经网络来处理二维图像数据。在语言模型和文本分类任务中&#xff0c;我们将文本数据看作是只有一个维度的时间序列&#xff0c;并很自然地使用循环神经网络来表征这样的数据。其实&#xff0c;我们也可以将文本当作…

安装 MySQL

1.下载安装文件 访问MySQL官网下载安装文件。 如下图所示&#xff0c;点击页面中的“DOWNLOAD”按钮。 点击下载之后自动进行下载。下载到本地的文件名称为&#xff1a;mysql-8.0.31-winx64.zip 2.解压安装文件 将压缩文件解压到你安装的目录&#xff0c;比如&#xff1a;F:…

数据结构与算法笔记

0 核心框架汇总 框架思维 数据结构的存储方式只有两种&#xff1a;数组&#xff08;顺序存储&#xff09;和链表&#xff08;链式存储&#xff09; 算法 数学中的算法重在推导&#xff0c;计算机中的算法重在穷举 计算机算法的本质特点&#xff1a; 穷举 穷举有两个关键难点…

Linux环境 java应用问题排查

0&#xff09;查看CPU占用高的进程PID top -d 1 或 top -H 注&#xff1a; top -d 1 中的 1 是数字&#xff1a;1&#xff0c;不是字母 &#xff1a;l 。 1&#xff09;查看内存使用情况&#xff08;memory-info.log为具体文件路径&#xff09; jmap -heap PID > memory-i…