redux全网最详细教程
一.路由懒加载
关键点:
lazy懒加载
Suspense组件(添加加载提示)
utils文件夹
–LazyLoad.js
//lazy懒加载 Suspense 组件(添加加载提示)
import {lazy,Suspense} from 'react'
export default function LazyLoad(url){//导入组件const Elem=lazy(()=>import('../pages'+url))//Suspense 提供一个加载提示return <Suspense fallback={<h2>loading...</h2>}><Elem></Elem></Suspense>
}
router文件夹–
baseRoutes.js
导入lazyLoad
import LazyLoad from "../utils/LazyLoad";
import Home from "../pages/Home";
import About from "../pages/About";
import Produce from "../pages/Produce";
// import OrderList from "../pages/admin/OrderList";
import Admin from "../pages/admin/Admin";
// import Dash from "../pages/admin/Dash"
import LazyLoad from "../utils/LazyLoad";
// 基本路由配置
const baseRoutes = [{path: "",element: <Home></Home>,},{path: "/about",element: <About></About>,},{path: "/produce/:id",element: <Produce></Produce>,},{path:"/admin/*",element:<Admin></Admin>,children:[{path:'',element:LazyLoad('/admin/Dash.js')},{path:'dash',element:LazyLoad('/admin/Dash.js')},{path:'orderlist',element:LazyLoad('/admin/OrderList.js')},]}];export default baseRoutes
index.js
import { useEffect, useState } from "react";
// useRoutes 根据路由配置 创建路由
import { useRoutes } from "react-router-dom";
import baseRoutes from "./baseRoutes";
function RouterView() { // 常见路由const element = useRoutes(baseRoutes);return <>{element}</>;
}
export default RouterView;
lazy Suspense
此时我们发现第一次点击的时候会出现路由懒加载,第二次就不再请求数据
react实现登录
npm i axios
- 定义request.js
utils —request.js
import axios from 'axios'
const request=axios.create({baseURL:"http://dida100.com:8888",timeout:5000})
request.interceptors.request.use(config=>{if(sessionStorage.getItem("token")){config.headers["Authorization"]="Bearer "+sessionStorage.setItem("token")}return config
})
export default request
- 定义api
新建server文件夹
user.js async 和 await 结合 数据请求完才往下走
import request from '../utils/request'
export async function loginServer(data){//async 和 await 结合const result=await request.post("/api/login",data)//状态码为200 成功if(result.status===200){return result.data}else{//请求失败//throw抛出 新的错误throw new Error("网络请求失败")}
}
- 实现登录
Home.js
(没有载荷是由于接口里面没写data) 这里面input实现双向绑定是通过onChange事件 onChange={e=>setUser({...user,password:e.target.value})}这里的...是扩展,就是面的name与password,用新的值去替换前面的password
import {loginServer} from '../server/user'
import {useState} from 'react'
import {useNavigate,useLocation} from 'react-router-dom'
import {parse} from '../utils'
function Home() {const [user,setUser]=useState({name:"",password:""})const navigate=useNavigate()const location=useLocation()var search=parse(location.search)function login(){loginServer(user).then(res=>{if(res.code===200){sessionStorage.setItem("token",res.token)sessionStorage.setItem("user",JSON.stringify(res.user))var redirect=search.redirect||'admin'navigate(redirect)}})}return ( <div>用户名:<input value={user.name} onChange={e=>setUser({...user,name:e.target.value})}/><br />密码:<input value={user.password} onChange={e=>setUser({...user,password:e.target.value})}/><br /><button onClick={login}>登录</button></div> );
}export default Home;
权限管理
通过新建一个组件实现的 pages页面新建一个private.js 如果有token就跳转到private的子组件props.children,如果没有就返回首页
import {Navigate,useLocation} from 'react-router-dom'
function Private(props) {const location=useLocation()console.log(location);if(sessionStorage.getItem("token")){return <>{props.children}</>}else{return <Navigate to={{pathname:'/',search:"?redirect="+location.pathname}} />;}}export default Private;
在路由基础配置中的element中,用<Private><Admin></Admin></Private进行包裹子组件Admin
import Private from "../pages/Private";
const baseRoutes = [
path:"/admin/*",
element:<Private><Admin></Admin></Private>,]
Home.js
import {useNavigate,useLocation} from 'react-router-dom'import {parse} from '../utils'const location=useLocation()
//把location的search转换为对象var search=parse(location.search)
如果search对象有redirext属性就用redirect,没有返回admin
var redirect=search.redirect||'admin'
utils里面 index.js
// 把?name=mumu&age=18
// 转换为{name:"mumu",age:18}
export function parse(url) {var temp = url.slice(1).split("&");var search = {};for (var i = 0; i < temp.length; i++) {var item = temp[i].split("=");search[item[0]] = item[1];}return search;}
redux(老版本)
单向数据流
组成
state状态数据
reducer处理状态的方法
store仓库
actions调用reducer的方法
安装
npm i redux react-redux redux-thunk redux-logger @reduxjs/toolkit -S
redux全局状态管理
react-redux 连接组件与redux
redux-thunk 处理异步actions
redux-logger 日志
redux-persist 本地存储
新建store
—index.js整个仓库
//整个仓库
// createStore 创建仓库,applyMiddleware处理中间件(日志,异步,本地存储)
// combineReducers合并多个处理counterReducer,userReducer,productionReducer
import {createStore,applyMiddleware,combineReducers} from 'redux'
//导入处理计数器
import counterReducer from './counterReducer'
//导入异步处理
import thunk from 'redux-thunk'
//导入日志
import logger from 'redux-logger'
//创建仓库
const store=createStore(combineReducers({counter:counterReducer}),applyMiddleware(thunk,logger)
)
//导出仓库
export default store
store有三个核心方法:
dispatch发起动作 触发reducer 返回新的state
subscribe 监听store中state的变化 执行回调函数
getState 获取stoTe中的数据
counterReducer.js 处理counter数据
import {INCREMENT} from './types'
//处理counter数据 定义初始化state
const initialState={num:1
}
//定义一个处理器function counterReducer(state=initialState,action){//根据动作的类型switch(action.type){case INCREMENT://如果是加,返回原来的数据state,把num值加1return {...state,num:state.num+1}default:return state}
}
export default counterReducer
counterAction.js调用CounterReducer动作
type后面跟的是常量,需要两个页面一致,所以我们
store --type.js 存放reducer动作类型
export const INCREMENT=“INCREMENT”
在其他页面导入,引号就可以去掉了,不容易出错,很规范
import {INCREMENT} from './types'
store有三个核心方法(原生):
dispatch发起动作 触发reducer 返回新的state
subscribe 监听store中state的变化 执行回调函数
getState 获取store中的数据
第一种方法
About.js
原生的三个都得写
这三个方法哪来的?
我们在index.js创建仓库的时候就带了这三个方法,通过createStore方法获取的
counter怎么来的?
const store=createStore( combineReducers({counter:counterReducer}), applyMiddleware(thunk,logger) )
dispatch(itype: “INCREMENT”})中的参数就是counterReducer的action根据type的值
//导入仓库 getState获取state
//dispatch发送事件执行 reducer改变state subscribe监听state数据的变化
import store from '../store/index.js'
//导入动作
import {add} from '../store/counterAction'
import {useEffect,useState} from 'react'
function About() { //创建value的状态 响应式更新store中的num 初始赋值const [value,setValue]=useState(store.getState().counter.num)useEffect(()=>{//监听store变化用store的num更新组件的valuestore.subscribe(()=>{setValue(store.getState().counter.num)})},[])return ( <div>about<p>value-store里面的num:{value}</p><button onClick={()=>store.dispatch(add())}>+</button></div>);
}export default About;
第二种方式 react-redux use方法
index.js
导入数据提供器Provider
import {Provider} from 'react-redux'
包装
<Provider store={store}> <App /> </Provider>
使用
const num=useSelector(state=>state.counter.num)const dispatch=useDispatch()
onClick={()=>dispatch({type:"INCREMENT"})}
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';//导入store
import store from './store'
//导入数据提供器
import {Provider} from 'react-redux'const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(// 渲染多次 去掉严格模式// <React.StrictMode><Provider store={store}><App /></Provider>// </React.StrictMode>
);
OrderList使用选择器useSelector
<button onClick={()=>dispatch({type:"INCREMENT"})}>{num}</button> <button onClick={()=>dispatch(add())}>{num}</button>
这俩方式都可以实现
//使用选择器
import {useSelector,useDispatch} from 'react-redux'
//导入动作
import {add} from '../../store/counterAction'
function OrderList() {//选择到state中的counter的numconst num=useSelector(state=>state.counter.num)//创建一个触发器const dispatch=useDispatch()return ( <div>orderlist<p>{/* 单击发送动作给reducer 处理返回新的state数据 */}<button onClick={()=>dispatch({type:"INCREMENT"})}>{num}</button><button onClick={()=>dispatch(add())}>{num}</button></p></div>);
}export default OrderList;
他们之前是同步的,其他页面也会改变
第三种方式
produce.js
import {useParams} from 'react-router-dom'
//导入连接器 把state和actions方法转换props
import {connect} from 'react-redux'
//导入counterAction 里面的所有动作方法
import * as actions from '../store/counterAction'
console.log(actions);
function Produce(props) {//获取产品参数const params=useParams()return ( <div>产品页面-{params.id}{/* <p onClick={()=>props.add()}>{props.counter.num}</p> */}<p onClick={()=>props.add()}>{props.num}</p></div>);
}
//props.counter.num从connect第一个参数 状态
//props.add 从connect的第二个参数 方法
// export default Produce;
export default connect(state=>({num:state.counter.num}),{add:actions.add})(Produce)
相关文章:
redux全网最详细教程
一.路由懒加载 关键点: lazy懒加载 Suspense组件(添加加载提示) utils文件夹 –LazyLoad.js //lazy懒加载 Suspense 组件(添加加载提示) import {lazy,Suspense} from react export default function LazyLoad(url)…...
华为OD机试 - 匿名信(Python)| 真题+思路+考点+代码+岗位
匿名信 题目 电视剧《分界线》里面有一个片段,男主为了向警察透露案件细节,且不暴露自己,于是将报刊上的字减下来,剪拼成匿名信。 现在又一名举报人,希望借鉴这种手段,使用英文报刊完成举报操作。 但为了增加文章的混淆度,只需满足每个单词中字母数量一致即可,不关注…...
【Python】编写代码实现指定下标值顺序进行正序和倒序排序算法编程
🎉🎉 在本次python文章中,主要通过定义一个排序方法,实现一组数列能够按照另一组数列指定的位置进行重新排序输出,默认正序排序,可通过True表示逆序输出 目录1、知识点2、数列和元组1)错误遍历方…...
Sitara™处理器的产品开发路线图
Sitara™处理器的产品开发路线图概述Evaluation Phase(评估阶段)Board Development Phase(硬件发展阶段,硬件设计人员应重点关注这个阶段)Software Development Phase(软件发展阶段)Product Phase/SW Lifecycle概述 一般情况下,会存在四个主要的发展阶段…...
岗位来啦-华为研发OD招聘
研发OD招聘 ★★关于我们★★ 万物互联时代已到来,无线通信技术正在重塑世界。作为行业领导者,华为无线致力于通过移动创新消除数字鸿沟,构建万物互联的智能世界。基于5G的技术,家庭无线宽带接入、车联网、云AR/VR、eMBB高清视频…...
【LeetCode】剑指 Offer 06. 从尾到头打印链表 p58 -- Java Version
题目链接: https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/ 1. 题目介绍(06. 从尾到头打印链表) 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 【测试用例…...
童年回忆--扫雷(包括标记功能和递归展开)--万字讲解让你学会扫雷制作
魔王的介绍:😶🌫️一名双非本科大一小白。魔王的目标:🤯努力赶上周围卷王的脚步。魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️…...
【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理
【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 1.前言 由计算机网络系统组成的分布式系统,若想协调一致进行:IT行业的“整点开拍”、“秒杀”、“Leader选举”,通信行业的“同步组网…...
软件测试未来发展趋势怎么样
未来,互联网技术是很多企业能够活下去的关键点。互联网技术成为新的基建,互联网“基建”化就决定了软件测试行业的缺口会一直扩大。 并且,软件测试岗位,已不仅局限于互联网企业,现已逐步深入到实体产业,金…...
aws Distro for OpenTelemetry 可观测性workshop记录
参考资料 https://aws-otel.github.io/docs/introductionhttps://aws-otel.github.io/docs/introduction aws distro for opentelemetry 官方提供了不同语言不同使用场景下完善的使用实例和相关配置。 AWS Distro for OpenTelemetrics 由以下部分组成,用于向后端…...
Leetcode力扣秋招刷题路-0068
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 68. 文本左右对齐 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。 你应该…...
Nginx介绍及安装(windows版,Linux版)
目录 一、Nginx介绍 1、Nginx优势 2、Nginx作用 3、部署静态资源 4、代理 5、负载均衡 二、Nginx安装步骤(windows版) 三、Nginx安装步骤(Linux版) 1、官网下载安装包,下载完之后上传到Linux系统上 2、在Lin…...
Camera | 4.瑞芯微平台MIPI摄像头应用程序编写
前面3篇我们讲解了camera的基础概念,MIPI协议,CSI2,常用命令等,本文带领大家入门,如何用c语言编写应用程序来操作摄像头。 Linux下摄像头驱动都是基于v4l2架构,要基于该架构编写摄像头的应用程序ÿ…...
【1250. 检查「好数组」】
来源:力扣(LeetCode) 描述: 给你一个正整数数组 nums,你需要从中任选一些子集,然后将子集中每一个数乘以一个 任意整数,并求出他们的和。 假如该和结果为 1,那么原数组就是一个「…...
Spring 如何解决循环依赖?
什么是循环依赖 ? 一个或多个对象之间存在直接或间接的依赖关系,这种依赖关系构成一个环形调用,有下面 3 种方式。 我们看一个简单的 Demo,对标“情况 2”。 Service public class Louzai1 {Autowiredprivate Louzai2 louzai2;…...
CocoaPods使用指南
前言 对于大多数软件开发团队来说,依赖管理工具必不可少,它能针对开源和私有依赖进行安装与管理,从而提升开发效率,降低维护成本。针对不同的语言与平台,其依赖管理工具也各有不同,例如 npm 管理 Javascri…...
Kafka 消息队列
目录主流的消息队列消息队列的应用场景缓存/肖锋解耦异步处理KafkaKafka的定义Kafka的底层基础架构Kafka分区如何保证Leader选举Kafka分区如何保证Leader和Follower数据的一致性Kafka 中消费者的消费方式Kafka 高效读写数据的原因(高性能吞吐的原因)&…...
华为OD机试 - 挑选字符串(Python)| 真题+思路+考点+代码+岗位
挑选字符串 题目 给定a-z,26 个英文字母小写字符串组成的字符串A和B, 其中A可能存在重复字母,B不会存在重复字母, 现从字符串A中按规则挑选一些字母可以组成字符串B 挑选规则如下: 同一个位置的字母只能挑选一次, 被挑选字母的相对先后顺序不能被改变, 求最多可以同时…...
对比Hashtable、HashMap、TreeMap有什么不同?
第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同? Map 是广义 Java 集合框架中的另外一部分,HashMap 作为框架中使用频率最高的类型之一,它本身以及相关类型自然也是面试考察的热点。 今天我要问你的问题是,对比 Hashtable、…...
测试新版Android Studio的手机镜像效果
学更好的别人, 做更好的自己。 ——《微卡智享》 本文长度为669字,预计阅读2分钟 前言 春节刚上班,就开始了疯狂出差的节奏,期间发现Android Studio发布新的版本2022.1.1(Electric Eel),里面两个更新的内容蓝牙模拟器和…...
女生可以参加IT培训吗?
2023年了,就不要把性别当作选择专业的前提条件了。虽然这句话说过很多次了,作为IT行业来说,是非常欢迎女生的加入;尤其是整天都是面对一大堆男攻城狮,工作氛围一点都不活跃,反而显得压抑和杂乱,…...
刷题25-重排链表
重排链表 解题思路:通过观察链表可以发现,把链表一分为二,后半段链表反转,然后两个链表穿插连接,当链表的节点总数是奇数时,要保证链表的前半段比后半段多一个节点。 关于把链表一分为二,可以…...
VHDL-延迟模型-惯性延迟与传输延迟
目录 1,惯性延时 2,传输延时 信号通过元件都会有延迟,延迟时间的计算是逻辑仿真的重要功能。考虑延迟信息得到的仿真输出波形可以更精确地反映实际电路的情况。针对元件的延时,人们根据需要建立了一些用的延时模型,这…...
2023年美赛(MCM/ICM)简介
2023年美赛将要如期开赛,这里为了 让大家对今年的美赛有一个直接 客观的了解。对2023年美赛(MCM/ICM)进行一下简要的介绍。相关资料大家可以查看另一篇文章一、竞赛时间February 16-20, 2023开赛时间 北京时间 17号(本周五) 6:00结束时间 北京时间 21号(…...
5min完成linux环境Jenkins的安装
5min搞定linux环境Jenkins的安装安装Jenkinsstep1: 使用wget 命令下载Jenkinsstep2、创建Jenkins日志目录并运行jekinsstep3、访问jenkins并解锁jenkins,安装插件以及创建管理员用户step4、到此,就完成了Finish、以上步骤中遇到的问题1、 jenkins启动不了…...
华为OD机试 - 字母计数(Python)| 真题+思路+考点+代码+岗位
字母计数 题目 给出一个只包含字母的字符串, 不包含空格,统计字符串中各个子字母(区分大小写)出现的次数, 并按照字母出现次数从大到小的顺序输出各个字母及其出现次数 如果次数相同,按照自然顺序排序,且小写字母在大写字母之前 输入 输入一行仅包含字母的字符串 输出 按…...
DENSE 数据集 - STF 数据集(CVPR 2020)
DENSE 数据集 - STF 数据集 - Seeing Through Fog Without Seeing Fog: Deep Multimodal Sensor Fusion in Unseen Adverse Weather(CVPR 2020)摘要1. 引言2. 相关工作3. 多模式恶劣天气数据集3.1 多模态传感器设置3.2 记录4. 自适应深度融合4.1 自适应多…...
华为OD机试 - 静态扫描最优成本(Python)| 真题+思路+考点+代码+岗位
静态扫描最优成本 题目 静态扫描快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出: 文件扫描的成本和文件大小相关,如果文件大小为 N ,则扫描成本为 N 个金币扫描报告的缓存成本和文件大小无关,每缓存一个报告需要 M 个金币扫描报告缓存后,后继再碰到该文件则不…...
【ns-3】零基础安装教程
文章目录前言1. 安装虚拟机及Ubuntu2. 安装依赖库3. 下载ns-34. 构建ns-3前言 近期因工作需要开始接触ns-3。作者零基础,从零开始顺利完成了ns-3的安装。本篇为ns-3安装过程记录贴或针对小白的零基础教程。 本篇内容所使用到的软件版本信息如下:VMware…...
华为OD机试 - 新学校选址(Python)| 真题+思路+考点+代码+岗位
新学校选址 题目 为了解新学期学生暴涨的问题,小乐村要建立所新学校 考虑到学生上学安全问题,需要所有学生家到学校的距离最短. 假设学校和所有学生家都走在一条直线之上,请问学校建立在什么位置, 能使得到学校到各个学生家的距离和最短 输入 第一行: 整数 n 取值范围 [1,1…...
惠阳开发网站建设/全媒体广告投放平台
点击上方"蓝字"关注我们,享更多干货!索引分裂(Index Block Split),就是索引块的分裂。当一次DML操作修改了索引块上的数据,但是旧有的索引块没有足够的空间去容纳新修改的数据时,将分…...
微擎可以做网站吗/企业培训机构排名
Dubbo服务发布源码解析 一. 服务发布概述 Dubbo服务发布影响流程的主要包括三个部分,依次是: 服务暴露;心跳;服务注册. 服务暴露是对外提供服务及暴露端口,以便消费端可以正常调用服务;心跳机制保证服务器端及客户端能够保持正常的长连接;服务注册是向注册中心注册服务暴露服…...
阿里云做网站/软文标题写作技巧
一道很好的字典树题目,用每组第二个单词构造字典树,最后一个节点存第一个单词,其他节点存ch,接着对每个输入进行查询 View Code 1 #include <iostream>2 #include <cstring>3 #include <cstdio>4 #define M 26…...
建设一个网站要多少钱/抚顺网络推广
网站微信登录,做起来挺简单的,我们做这个,首页是要去看微信文档,文档看懂了,然后理清楚逻辑,怎么进行绑定贵公司的账号,业务那块要理清楚! 首先,微信官方告诉我们&#…...
做网站的目标是什么/东莞seo项目优化方法
Linux指令篇:讯息传送与信件管理--write(转)名称 : write使用权限 : 所有使用者使用方式 :write user [ttyname]说明 : 传讯息给其他使用者参数 :user : 预备传讯息的使用者帐号ttyname : 如果使用者同时有两个以上的 tty 连线,可以自行选择合适的 tty 传讯息例子.1…...
公司商城网站建设/百度指数的搜索指数
项目名:俄罗斯方块 组名:新蜂 测试者:韩媛媛(nice!团队) 用户需求规格说明书URL:http://www.cnblogs.com/Boxer1994/p/6084035.html 组长博客URL:http://www.cnblogs.com/Boxer1994/…...