React-Redux(一)

​🌈个人主页:前端青山
🔥系列专栏:React篇
🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来React篇专栏内容:React-Redux(一)

目录

1、简介

2、三大原则(重点)

3、redux的基本使用

1、简介

2013年Facebook提出了Flux架构的思想,引发了很多的实现。2015年,Redux出现,将Flux与函数式编程结合一起,很短时间内就成为了最热门的前端架构。

简单说,如果你的UI层非常简单,没有很多互动,Redux就是不必要的,用了反而增加复杂性。

如果你的项目的迭代变得越来越复杂,组件的数量和层级也变得越来越多,越来越深,此时组件间的数据通信就变得异常的复杂和低效,为了解决这个问题,引入了状态管理(redux)从而很好的解决多组件之间的通信问题。

如果需要使用Redux请先进行安装:

网址:Getting Started with Redux | Redux

npm i -S redux

作用:项目进行大规模数据管理的工具。

提醒:所有的代码需要从0开始写(不像vuex,选择了vuex后会自带一些代码)

2、三大原则(重点)

  • 单一数据源

    • 整个应用的state(这个state不是组件中的state,请不要混淆)被储存在一棵对象结构树中,并且这个对象结构只存在于唯一一个store中

  • State是只读(相对,相对旧数据)的

    • 唯一改变state的方法就是触发dispatch+action,action是一个用于描述已发生事件的普通对象(action普通对象必须要有type属性,值是什么无所谓,其余属性也无所谓)。

  • (最终修改数据的方法)使用纯函数(一个函数的返回结果只受到其形参的影响,则其就是纯函数)来执行修改

    • 为了描述action如何改变state tree ,我们需要编写reducer【看作是vuex中的mutations里的方法】,==reducer必须是纯函数==,它接收先前的state和action,并返回新的state(不会合并的,自行注意这个坑)

纯函数是函数式编程的概念,必须遵守以下一些约束。

  • 不得改写参数

  • 不能调用系统 I/O 的API

  • 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果

请注意:由于reducer被要求是纯函数,所以reducer函数里面不能改变State,必须返回一个全新的数据(不会自动合并原始数据的,因此一定要注意:别把原始数据搞丢了)。

操作原理图

a. store通过reducer创建了初始状态

b. view通过store.getState()获取到了store中保存的state挂载在了自己的状态上

c. 用户产生了操作(事件),调用了actions 的方法

d. actions的方法被调用,创建了带有标示性信息的action(描述对象,描述如何修改数据)

e. actions将action通过调用store.dispatch方法发送到了reducer中

f. reducer接收到action并根据标识信息判断之后返回了新的state(自己注意合并的问题)

g. store的state被reducer更改为新state的时候,store.subscribe方法里的回调函数会执行,此时就可以通知view去重新获取state

  • store.getState():用于获取仓库中初始的数据(一次性)

  • store.dispatch():用于派发修改数据的任务,参数是action普通对象

  • store.subscribe(callback):视图组件用于订阅新数据的方法(二次及以后的数据更新,使之产生类似于vue的响应式store数据)

3、redux的基本使用

案例:在组件中展示一个按钮,点按钮后给redux中的数字+9,数字初始为0。实现一个计数器的效果

步骤:

  • 创建store

  • 创建视图组件(展示store中的数据)

  • 修改

  • 回显数据到视图组件

实现步骤

a. 创建默认数据源:

// 1. 这是仓库store
​
// a. 导入需要使用的成员
// createStore方法,作用用于产生仓库
import { createStore } from "redux";
​
// b. 创建数据源
// 默认数据源是一个普通对象,可以有很多的数据
const defaultState = {// 定义初始化的数据count: 0,
};
​
// c. 创建纯函数reducer(方法名叫什么无所谓)
// 作用:负责返回state(可能是直接返回state,也可能是返回修改后的state)
// 语法:reducer(state = defaultState,actions)
function reducer(state = defaultState, actions) {// 在返回之前写修改数据源的操作return state;
}
​
// d. 产生仓库
// 产生仓库的时候需要往仓库中存放数据源,因此需要传递reducer过去
const store = createStore(reducer);
​
// e. 导出仓库
export default store;

为了方便调试redux(可选安装),建议去谷歌商店安装redux dev tools,在使用的时候需要参考其说明页面

redux工具条在安装好之后不能直接使用,需要配置仓库代码,然后才能使用。

// d. 产生仓库
// 产生仓库的时候需要往仓库中存放数据源,因此需要传递reducer过去
const store = createStore(reducer,// 必须要加上一段插件的配置工具,才能在浏览器中使用redux扩展window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

显示效果:

b. 建立视图组件并且展示数据源

import React, { Component } from "react";
// 需要导入store
import store from "../store/index";
class Counter extends Component {// 在constructor中获取store中的数据constructor(props) {super(props);// 获取store数据(一次性,不具备响应式)this.state = store.getState();// 订阅数据的更新store.subscribe(() => this.setState(() => store.getState()));}render() {console.log(this.state);return (<div><div>当前Store中的数据是:{this.state.reducer.count}</div><button onClick={this.addCount.bind(this)}>点击+9</button><hr /><div>当前Store中的数据是:{this.state.reducer2.age}</div><button onClick={this.addAge.bind(this)}>点击+1</button></div>);}
​// 点击+9addCount() {// 描述数据如何更改的对象,其必须有type属性let action = { type: "mod_count", payload: 9 };// 通过store.dispatch去派发action(会将该action派发给所有的reducer,每个reducer都会被执行,因此一定要注意type的取值)store.dispatch(action);}
​// 点击+1addAge() {let action = { type: "mod_age", payload: 1 };store.dispatch(action);}
}
​
export default Counter;

c. 修改操作

视图组件中的代码:

handler() {// 3. +9这个修改操作需要通过普通对象去描述(actions)const action = {// type是用于在reducer方法中做条件判断用的type: "add",// 另一个属性用于声明本次修改具体的值是多少payload: 9,};// 派发修改任务store.dispatch(action);
}

仓库文件的代码:

function reducer(state = defaultState, actions) {console.log(actions);//判断是否是加法操作if (actions.type === "add") {return { count: state.count + actions.payload };}// 在返回之前写修改数据源的操作return state;
}

d. 回显新的数据

// 构造函数
constructor(props) {super(props);// 2. 在视图组件中获取初始的仓库数据// getState()方法是store对象内置的方法this.state = store.getState();// 4. 订阅新的数据store.subscribe(() => {// 获取新数据修改当前的statethis.setState(() => store.getState());});
}

如果有多个reducer,需要通过combineReducers方法进行合并,代码如下:

// 合并reducer
// 有点类似于vuex的命名空间
const reducers = combineReducers({ reducer, reducer2 });
​
// c. 创建store对象(通过createStore方法),目前(后续有变)其参数就是reducer
const store = createStore(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

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

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

相关文章

ECharts数据大屏展示效果

ECharts数据大屏展示效果 前言1、效果预览1.2、视频效果 2、使用框架3、如何处理屏幕自适应效果4、ECharts模块、dataV大屏插件 编写与布局5、往期回顾总结&#xff1a; 前言 数据大屏需整体效果好看&#xff0c;界面缩放自适应大小&#xff0c;全屏展示铺满整个屏幕并自适应&a…

HTML段落标签、换行标签、文本格式化标签与水平线标签

目录 HTML段落标签 HTML换行标签 HTML格式化标签 加粗标签 倾斜标签 删除线标签 下划线标签 HTML水平线标签 HTML段落标签 在网页中&#xff0c;要把文字有条理地显示出来&#xff0c;就需要将这些文字分段显示。在 HTML 标签中&#xff0c;<p>标签用于定义段落…

Golang面试题四(GMP)

目录 1.Goroutine 定义 2.GMP 指的是什么 3.GMP模型的简介 全局队列&#xff08;Global Queue&#xff09; P的本地队列 P列表 M列表 4.有关P和M的个数问题 P的数量问题 M的数量问题 P和M何时会被创建 5.调度器P的设计策略 复⽤线程 work stealing机制 hand off…

算法 第41天 动态规划3

343 整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 # 动态规划 def integerBreak(n:int)->int:dp[0]*(n1)dp[2]1 #从下标为2开始 &#xff0…

本地生活服务平台都有哪些,靠谱吗?

随着本地生活服务的发展潜力和盈利方式被不断挖掘&#xff0c;越来越多的人开始发现其中所蕴含着的巨大商机&#xff0c;大家所熟悉的抖音、小红书和支付宝等平台也纷纷上线了本地生活板块&#xff0c;再次印证了其前景的广阔。在此背景下&#xff0c;普通人想要趁势入局分一杯…

定制k8s域名解析------CoreDns配置实验

定制k8s域名解析------CoreDns配置实验 1. 需求 k8s集群内通过CoreDns互相解析service名. 同时pana.cn域为外部dns解析,需要通过指定dns服务器进行解析 再有3个服务器,需要使用A记录进行解析 2. K8s外DNS服务器 查看解析文件 tail -3 /var/named/pana.cn.zone 解析内容 ww…

免费申请泛域名证书

通配符证书是一种比较特殊的SSL/TLS 证书&#xff0c;可用于保护多个域名&#xff08;含主域名&#xff09;&#xff0c;由域名字段中的通配符 (*) 指示。这种证书主要用于具有很多子域的组织。通配符证书对主域及其所有次级子域有效。 对于免费通配符证书而言&#xff0c;目前…

IAR 使用笔记(IAR BIN大小为0异常解决)

烧写 由于芯片的内部SPI FLASH的0级BOOT 程序起到到开启JTAG SW 仿真功能&#xff0c;一旦内部SPI FLASH存储的BL0启动代码被损坏&#xff0c;芯片的JTAG 将不能被连接。所以对BL0的烧写需要谨慎&#xff0c;烧写BL0过程保证芯片不断电。 如果烧写了多备份的启动代码&#xff…

NLP基础—jieba分词

jieba分词 支持四种分词模式 精确模式 试图将句子最精确地切开,适合文本分析;全模式 把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;搜索引擎模式 在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。paddle模式 利用Paddle…

Spring Boot 处理过滤器(filter )中抛出的异常

前言&#xff1a; 在改造老项目登录功能的时候&#xff0c;使用了过滤器对 token 进行有效性验证&#xff0c;验证通过继续进行业务请求&#xff0c;验证不通过则抛出校验异常。 过程&#xff1a; 技术方案拟定后&#xff0c;就着手开始改造&#xff0c;一切都很顺畅&#x…

Oracle子查询

这里写目录标题 子查询子查询的分类1.非相关子查询单行单列单行多列单列多行多行多列 2.相关子查询 子查询 定义&#xff1a;一个查询语句中嵌套一个或多个查询语句&#xff0c;里层的查询语句的结果成为了外层查询语句的一部分。 外层的查询叫主查询 里层的查询叫子查询 子查…

Linux学习:进程(5)进程控制

目录 1. 进程创建1.1 进程创建的方式与过程1.2 写时拷贝1.3 补充知识 2. 进程终止2.1 main函数返回值与进程退出码2.2 进程退出码的意义2.3 进程的执行结果与异常信号2.4 进程终止方式&#xff1a;exit与_exit 3. 进程等待3.1 进程创建与回收3.2 进程等待与回收的方式3.3 wait与…

鸿蒙语言TypeScript学习第18天:【泛型】

1、TypeScript 泛型 泛型&#xff08;Generics&#xff09;是一种编程语言特性&#xff0c;允许在定义函数、类、接口等时使用占位符来表示类型&#xff0c;而不是具体的类型。 泛型是一种在编写可重用、灵活且类型安全的代码时非常有用的功能。 使用泛型的主要目的是为了处…

树莓派安装tensorflow

树莓派安装tensorflow 使用编译好的版本自己选择版本进行编译armv71 架构 教程转载 使用编译好的版本 下载tensorflow编译好的版本 https://github.com/lhelontra/tensorflow-on-arm/tags由于python版本支持有限可能需要自己安装python 安装对应的python 自己选择版本进行编译…

【动态规划】【01背包 给定背包容量,装满背包最多有多少个物品】Leetcode 474. 一和零

【动态规划】【01背包 给定背包容量&#xff0c;装满背包最多有多少个物品】Leetcode 474. 一和零 解法 ---------------&#x1f388;&#x1f388;474. 一和零 题目链接&#x1f388;&#x1f388;------------------- 纯 0 - 1 背包 是求 给定背包容量 装满背包 的最大价值…

【随笔】Git 高级篇 -- 远程与本地不一致导致提交冲突 git push --rebase(三十一)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

如何爬出 Kotlin 协程死锁的坑?

作者&#xff1a;悬衡 一、前言 在 Java 中有一个非常经典的死锁问题, 就是明明自己已经占用了线程池, 却还继续去申请它, 自己等自己, 就死锁了, 如下图和代码: // 这段代码将死锁到天荒地老final ExecutorService executorService Executors.newSingleThreadExecutor();exe…

【C 数据结构】单链表

文章目录 【 1. 基本原理 】1.1 链表的节点1.2 头指针、头节点、首元节点 【 2. 链表的创建 】2.0 创建1个空链表&#xff08;仅有头节点&#xff09;2.1 创建单链表&#xff08;头插入法&#xff09;*2.2 创建单链表&#xff08;尾插入法&#xff09; 【 3. 链表插入元素 】【…

爱之旅 | 爱的守望与宽恕

爱其实是一种持续的稳定情绪输出与反馈的表现。 情绪稳定的前提是丰富。 比如生活的丰富&#xff0c;有物质财富、社会关系、健康、知识和经验等。 一个人的生活如果多元化&#xff0c;拥有丰富的兴趣爱好、健康的社交关系、持续的个人成长&#xff0c;在面对生活中的挑战时自…

【SpringBoot实战篇】登录认证

&#x1f340;&#x1f338;明确需求--接口文档--思路分析--开发--测试&#x1f338;&#x1f340;&#x1f495; 1 明确需求 2 接口文档 登录 3 思路分析 UserServic、UserMapper在注册的时候已经实现 现在我们重点看UserController 控制器 4 开发&#xff08;实现&#xff0…