react笔记-04redux篇
redux和react-redux笔记,以及项目中如何使用,对redux的封装,让其使用类似于vuex一样方便。
一、redux
1. redux工作流程
流程:创建action
=> dispatch
分发action
=> 交给store
=> reducer
加工数据返回给store
2. redux的三个核心概念
2.1 action
动作对象,包含两个属性:
- type:标识属性,值为
string
,唯一,必要属性 - data:数据属性,值类型任意,可选属性
{ type: 'userInfo', data: { name: 'xiaotian', age: 20 } }
2.2 reducer
用于初始化状态、加工状态。加工时,根据旧的state
和action
,产生新的state
的纯函数。redux的reducer函数必须是一个纯函数。
纯函数:同样的输入,同样的输出
遵循:
- 不得改写参数数据
- 不会产生任何副作用,例如:网络请求,输入输出设备
- 不能调用
Date.now()
或者Math.random()
等不纯的方法例如:下面这个函数就不是纯函数
// 传入同样的参数num,每次返回的结果都不相同,所以不是纯函数。 function fn(num) {return Math.random() + num }
错误写法:
let personList = []
export default function personReducer(preState = personList, action) {const { type, data } = actionswitch (type) {case 'AddPerson':// 不能这样写,会导致personList被改写了,personReducer就不是一个纯函数了,会导致reducx不能识别到数据的改变。personList.unshift(data)return personListdefault:return preState}
}
正确写法:
let personList = []
export default function countReducer(preState = personList, action) {const { type, data } = actionswitch (type) {case 'AddPerson':return [data, ...personList]default:return preState}
}
2.3 store
用于存储数据,有如下方法:
-
getState()
: 获取当前的state对象。 -
dispatch(action)
: 分发action,这是改变state的唯一途径。每个action是一个描述“发生了什么”的普通JavaScript对象。 -
subscribe(() => {})
: 注册一个监听器,当state发生改变时,会调用该回调。
3. redux使用
3.1 安装redux
npm install redux
3.2 基本使用
- 新建
redux
目录,在redux
目录下新建store.js
和xxx.js
store.js
// 引入legacy_createStore,专门用于创建redux中最核心的store对象
import { legacy_createStore } from 'redux'
// 引入为xxx组件服务的reducer
import countReducer from './count_reducer'// 用于暴露一个store对象,整个应用只有一个store
export default legacy_createStore(countReducer)
xxx.js
(这里是count_reducer.js
)
创建一个为xxx组件服务的reducer,reducer的本质就是一个函数
countReducer有两个参数:preState(之前的状态)、action(动作对象)
reducer第一次调用时,是store自动触发的,传递的preState是undefined,action是@@REDUX/INITxxx
export default function countReducer(preState = 0, action) {// 从action对象中获取:type、dataconst { type, data } = action// 根据type决定如何加工数据switch (type) {case 'increment':return preState + data case 'decrement':return preState - datadefault:return preState}
}
getState
:获取store
中的state
数据
store.getState()
dispatch
:store
派发数据(更新数据)
store.dispatch({ type: 'increment', data: xxx })
subscribe
:监听store
中的数据变化
store.subscribe(() => {// 调用render,渲染页面
})
组件中使用:
componentDidMount() {store.subscribe(() => {this.setState({})})
}
全局index.js
中使用:
import store from './redux/store'const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<React.StrictMode><BrowserRouter><App /></BrowserRouter></React.StrictMode>
)store.subscribe(() => {root.render(<React.StrictMode><BrowserRouter><App /></BrowserRouter></React.StrictMode>)
})
3.3 异步action
- action分类:
- 同步action:一般对象类型,
{type: string, data: any}
- 异步action:函数类型
- 异步action的使用:
组件中:
import React, { Component } from 'react'
import store from '../redux/store'
import { createIncrementAction, createAsyncIncrementAction } from '../redux/count_action'export default class count extends Component {handleAsyncIncrement = () => {const { value } = this.selectNumberstore.dispatch(createAsyncIncrementAction(value))}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><button onClick={this.handleAsyncIncrement}>异步加</button></div>)}
}
count_action.js中(用于创建action对象):
// 异步action:指action的值是函数,异步action中都会调用同步action去真正的操作数据
export const createAsyncIncrementAction = (data) => {return (dispatch) => {// 由redux调用,传递参数dispatchsetTimeout(() => {dispatch({ type: 'increment', data: data * 1 })}, 1000)}
}
⚠️注意:redux的action默认是不支持函数类型的,需要使用中间件
redux-thunk
。安装:
npm install redux-thunk
store.js中:
import { legacy_createStore, applyMiddleware } from 'redux'
// 引入redux-thunk,用于支持异步action
import { thunk } from 'redux-thunk'
import countReducer from './count_reducer'export default legacy_createStore(countReducer, applyMiddleware(thunk))
这样就可以使用异步action了。
二、react-redux(类式组件中使用)
react-redux搭配redux使用步骤:
1. 目录结构
- components: 存放UI组件
- containers: 存放容器组件
- redux: 存放redux仓库
2. react-redux的基本使用
2.1 redux
store.js: 创建store
import { legacy_createStore, applyMiddleware } from 'redux'
import count_reducer from './count_reducer'
import { thunk } from 'redux-thunk'export default legacy_createStore(count_reducer, applyMiddleware(thunk))
count_reducer.js
export default function countReducer(preState = 0, action) {const { type, data } = actionswitch (type) {case 'ADD':return preState + datadefault:return preState}
}
2.2 containers(容器组件): containers/count.jsx
容器组件的store是靠父组件的props传递进去的(2.3的App.jsx),而不是自己import引入的
// 引入cont的ui组件
import CountUI from '../components/count'
// 引入connect用于连接ui组件和redux
import { connect } from 'react-redux'// 1. mapStateToProps函数的返回的是一个对象
// 2. 返回对象中的key就作为传递给ui组件的props的key,value就作为传递给ui组件props的value
// 3. mapStateToProps函数的本质:传递状态,把状态传递给props
function mapStateToProps(state) {return {count: state}
}// 1. mapDispatchToProps函数的返回的是一个对象
// 2. 返回对象中的key就作为传递给ui组件的props的key,value就作为传递给ui组件props的value
// 3. mapDispatchToProps函数的本质:传递操作状态的方法
function mapDispatchToProps(dispatch) {return {add: () => {console.log('add')dispatch({ type: 'ADD', data: 1 })}}
}// 使用connect()()创建并暴露一CountUI的容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)
2.3 App.jsx
⚠️注意:这里引入的Count组件是容器组件(2.2 创建的),而不是UI组件
通过props的方式,将store传入给容器组件,在mapStateToProps
中就可以获取到state
,mapDispatchToProps
中可获取到dispatch
import React, { Component } from 'react'
import Count from './containers/count'
import store from './redux/store'export default class App extends Component {render() {return <><div><h1>App</h1><Count store={store} /></div></>}
}
2.4 components(UI组件): components/count.jsx
这个时候通过this.props
即可获取redux的store仓库中数据和方法(在2.2容器组件定义的数据和方法)
import React, { Component } from 'react'export default class count extends Component {handleAdd = () => {this.props.add()}render() {// console.log('ui组件props', this.props)return (<div><p>num为: {this.props.count}</p><button onClick={this.handleAdd}>+1</button></div>)}
}
3. 优化
3.1 优化1:容器组件mapDispatchToProps
的简写
mapDispatchToProps可以是函数,也可以是对象
value只要返回action,react-redux自动dispatch分发action
// 引入cont的ui组件
import CountUI from '../components/count'
// 引入connect用于连接ui组件和redux
import { connect } from 'react-redux'export default connect(state => ({count: state}),// mapDispatchToProps的简写{add: () => ({ type: 'ADD', data: 1 })}
)(CountUI)
3.2 优化2:不用再手动监测redux数据的变化,react-redux自动监测
3.3 优化3:Provider使用
如果有多个容器组件,需要每个容器组件都传入store,就类似这样:
<Count store={store} />
<Demo store={store} />
<Text store={store} />
优化:可以通过Provider
向每个容器组件都传入store,在入口文件中如下使用:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { Provider } from 'react-redux'
import store from './redux/store.js'ReactDOM.createRoot(document.getElementById('root')).render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>,
)
需要组件的地方直接使用即可:
<Count />
3.4 整合:UI组件+容器组件
import React, { Component } from 'react'
import { connect } from 'react-redux'// ui组件
class count extends Component {handleAdd = () => {this.props.add()}render() {return (<div><p>num为: {this.props.count}</p><button onClick={this.handleAdd}>+1</button></div>)}
}// 容器组件
export default connect(state => ({count: state}),{add: () => ({ type: 'ADD', data: 1 })}
)(count)
4. 多个reducer的使用
store.js中:
import { legacy_createStore, applyMiddleware, combineReducers } from 'redux'
import count_reducer from './reducers/count'
import person_redercer from './reducers/person'
import { thunk } from 'redux-thunk'// 汇总所有的reducer变成一个总的reducer
const allReducer = combineReducers({count: count_reducer,personList: person_redercer
})export default legacy_createStore(allReducer, applyMiddleware(thunk))
容器组件中:
import React, { Component } from 'react'
import { connect } from 'react-redux'class count extends Component {handleAdd = () => {// 操作状态的方法不需要区分this.props.add()}render() {return (<div><p>num为: {this.props.count}</p><button onClick={this.handleAdd}>+1</button><div>{this.props.personList.length}</div></div>)}
}export default connect(state => ({// state.xxx:xxx是根据store.js中的allReducer中的key值决定的count: state.count,personList: state.personList}),{add: () => ({ type: 'ADD', data: 1 })}
)(count)
5. redux开发者工具的使用
5.1 下载浏览器插件
下载地址:https://chrome.zzzmh.cn/info/lmhkpmbekcpmknklioeibfkpmmfibljd
5.2 项目中安装
npm i redux-devtools-extension
5.3 在store.js中配置
import { legacy_createStore, applyMiddleware } from 'redux'
import count_reducer from './reducers/count'
import { thunk } from 'redux-thunk'
// 引入开发者工具
import { composeWithDevTools } from 'redux-devtools-extension'export default legacy_createStore(count_reducer, composeWithDevTools(applyMiddleware(thunk)))
这样浏览器插件就会亮了。
三、react-redux(函数式组件使用)
1. 可以通过UI组件和容器组件结合的写法:
import { connect } from 'react-redux'const CountUI = (props) => {return (<div><h1>当前求和为:{props.count}</h1><button onClick={props.add}>+1</button></div>)
}function mapStateToProps(state) {return {count: state}
}function mapDispatchToProps(dispatch) {return {add: () => {console.log('add')dispatch({ type: 'ADD', data: 1 })}}
}export default connect(mapStateToProps, mapDispatchToProps)(CountUI)
2. Hooks写法(推荐)
2.1 创建仓库
import { legacy_createStore } from 'redux'
import reducer from './reducer'// window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 配置redux-devtools
const store = legacy_createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store
2.2 创建reducer(初始化仓库数据,和修改仓库数据)
// 仓库数据
const defaultState = {num: 0
}// 当调用dispatch的时候会触发函数
let reducer = (state = defaultState, action) => {// action:dispatch传递过来的对象// 对数据进行深拷贝let newState = JSON.parse(JSON.stringify(state))switch (action.type) {case 'ADD1':newState.num += 1break;case 'ADD2':newState.num -= action.numbreak;default:break;}return newState
}export default reducer
2.3 在main.js
中将store与项目关联
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { Provider } from 'react-redux'
import store from './store/index.js'ReactDOM.createRoot(document.getElementById('root')).render(<Provider store={store}><App /></Provider>
)
2.4 在组件中获取仓库数据和修改仓库数据(2.2关联)
- 获取仓库数据:通过
useSelector
获取 - 修改仓库数据:通过
useDispatch
获取
import { useSelector, useDispatch } from "react-redux"export default () => {// 通过useSelector获取仓库数据,回调返回一个对象或数组const { num } = useSelector((state) => {return {num: state.num}})// 修改仓库数据const dispatch = useDispatch()const changeNum = () => {// dispatch({type: '字符串', val: 'val可以自定义,也可以不传'})dispatch({type: 'ADD1'})}const changeNum2 = () => {dispatch({type: 'ADD2', val: 2})}return (<div><p>{num}</p><button onClick={changeNum}>num1</button><button onClick={changeNum2}>num2</button></div>)
}
3. 对react-redux的优化
3.1 将state数据抽离
- 新建
index.js
用于存放数据和方法
// index.js 用于存放数据
// src/store/index.js 用于存放num模块数据
export default {state: {num: 0},actions: {ADD1(newState, action) {newState.num += 1},ADD2(newState, action) {newState.num += action.val}},// 名字统一管理actionsName: {add1: 'ADD1',add2: 'ADD2'}
}
reducer.js
// 仓库数据
import handleStore from './index'
const defaultState = {// num: handleStore.state.num 多个属性这么写会很麻烦...handleStore.state
}// 当调用dispatch的时候会触发函数
let reducer = (state = defaultState, action) => {// action:dispatch传递过来的对象// 对数据进行深拷贝let newState = JSON.parse(JSON.stringify(state))switch (action.type) {case handleStore.actionsName.add1:// handleStore.actions.ADD1(newState, action)// 将add1抽离handleStore.actions[handleStore.actionsName.add1](newState, action)break;case handleStore.actionsName.add2:handleStore.actions[handleStore.actionsName.add2](newState, action)break;default:break;}return newState
}export default reducer
页面的使用参考2.4
3.2 仓库模块化
仓库目录结构:
modules
:用于对模块进行划分- 不同模块目录:
index.js
:用于存放仓库数据和方法reducer.js
:创建不同模块的reducer
index.js
:redux仓库
拆分优化过程:
index.js
进行reducer合并
import { legacy_createStore, combineReducers, } from 'redux'
import num_reducer from './modules/num/reducer'
import arr_reducer from './modules/arr/reducer'const reducers = combineReducers({num_module: num_reducer,arr_module: arr_reducer
})const store = legacy_createStore(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store
页面上展示使用:
import { useSelector, useDispatch } from "react-redux"export default () => {const { num } = useSelector((state) => {return {// 需要加上模块名称使用num: state.num_module.num}})const dispatch = useDispatch()const changeNum = () => {dispatch({ type: 'ADD1' })}const changeNum2 = () => {dispatch({ type: 'ADD2', val: 2 })}const { arr } = useSelector((state) => {return {// 需要加上模块名称使用arr: state.arr_module.arr}})const arrPush = () => {dispatch({ type: 'ARRPUSH', val: 40 })}return (<div><p>{num}</p><button onClick={changeNum}>num1</button><button onClick={changeNum2}>num2</button><hr /><p>{arr}</p><button onClick={arrPush}>push</button></div>)
}
- 对每个模块的
reducer.js
中的switch
语句进行优化
// 仓库数据
import handleStore from './index'
const defaultState = {// num: handleStore.state.num 多个属性这么写会很麻烦...handleStore.state
}// 当调用dispatch的时候会触发函数
let reducer = (state = defaultState, action) => {// action:dispatch传递过来的对象let newState = JSON.parse(JSON.stringify(state))// 优化前:// switch (action.type) {// case handleStore.actionsName.add1:// // handleStore.actions.ADD1(newState, action)// // 将add1抽离// handleStore.actions[handleStore.actionsName.add1](newState, action)// break;// case handleStore.actionsName.add2:// handleStore.actions[handleStore.actionsName.add2](newState, action)// break;// default:// break;// }// 优化后for (const key in handleStore.actionsName) {if (action.type === handleStore.actionsName[key]) {handleStore.actions[action.type](newState, action)break}}return newState
}export default reducer
- 根据每个模块的
index.js
中的actions
的名字自动生成actionsName
,也可以将actionsName
进行提取到单独文件统管理
const store = {state: {num: 0},actions: {ADD1(newState, action) {newState.num += 1},ADD2(newState, action) {newState.num += action.val}},// 名字统一管理(最好将key=value=actions的方法名)// actionsName: {// ADD1: 'ADD1',// ADD2: 'ADD2'// }
}let actionsName = {}
for (const key in store.actions) {actionsName[key] = key
}
Object.assign(store, { actionsName })export default store
效果及其如何使用:
- 效果:做到了只有修改每个模块的
index.js
中的数据和方法,不去动reducer.js
文件,使用起来跟``vuex`一样 - 复制
index.js
和reducer.js
,在index.js
的state
中添加数据,actions
添加方法即可;在store/index.js
中引入不同模块的reducer
4. 异步action
4.1 跟之前的一样,需要安装redux-thunk
4.2 在store/index.js
中配置
import { legacy_createStore, combineReducers, compose, applyMiddleware } from 'redux'
import { thunk } from 'redux-thunk'
import num_reducer from './modules/num/reducer'
import arr_reducer from './modules/arr/reducer'const reducers = combineReducers({num_module: num_reducer,arr_module: arr_reducer
})// 判断是否有__REDUX_DEVTOOLS_EXTENSION__COMPOSE__这个开发者工具模块
let composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION__COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION__COMPOSE__() : composeconst store = legacy_createStore(reducers, composeEnhancers(applyMiddleware(thunk)))
export default store
4.3 组件中使用
import { useSelector, useDispatch } from "react-redux"export default () => {const { num } = useSelector((state) => {return {num: state.num_module.num}})const dispatch = useDispatch()const asyncChangeNum = () => {// 异步用法:dispatch中传入回调dispatch((disp) => {setTimeout(() => {disp({ type: 'add1', val: 1 })}, 1000)})}return (<div><p>{num}</p><button onClick={asyncChangeNum}>num异步+1</button></div>)
}
4.4 优化:将组件内的方法抽取到每个模块的index.js
中
index.js
:
const store = {state: {num: 0},actions: {add1(newState, action) {newState.num += action.val}},// 异步方法asyncActions: {asyncAdd1(dispathch) {setTimeout(() => {dispathch({ type: 'add1', val: 1 })}, 1000)}}
}let actionsName = {}
for (const key in store.actions) {actionsName[key] = key
}
Object.assign(store, { actionsName })export default store
组件内:
import { useSelector, useDispatch } from "react-redux"export default () => {const { num } = useSelector((state) => {return {num: state.num_module.num}})const dispatch = useDispatch()const asyncChangeNum = () => {// 异步用法:dispatch中传入回调dispatch(调用asyncAdd1方法即可)}return (<div><p>{num}</p><button onClick={asyncChangeNum}>num异步+1</button></div>)
}
相关文章:

react笔记-04redux篇
redux和react-redux笔记,以及项目中如何使用,对redux的封装,让其使用类似于vuex一样方便。 一、redux 1. redux工作流程 流程:创建action > dispatch分发action > 交给store > reducer加工数据返回给store 2. redux的…...

oracle 等待事件
1.db file scattered read 含义:当一个SQL语句需要从数据文件中读取多块非连续的数据块时,就会发生db file scattered read等待事件。这意味着数据分散在不同的位置,数据库需要进行多次I/O操作来收集所需的信息。场景:这种事件常…...

Vue 的 axios二次封装
(以下的接口地址链接换成自己的写!!!) 首先在项目中src的目录下创建一个api的文件夹,在api的文件下在穿件两个文件用于二次封装 别忘了先安装axios:(在根目录下安装axios࿰…...

实验操作步骤:使用Tripwire进行文件完整性监控
摘要 在网络安全领域,文件完整性监控是确保系统安全的关键措施之一。Tripwire作为一个业界领先的文件完整性监控工具,能够帮助系统管理员检测未授权的文件更改。本文将详细介绍如何安装、配置并使用Tripwire进行文件完整性监控的实验操作步骤。 1. Tri…...

使用达梦DMHS平滑迁移Oracle数据到DM8
一、迁移前准备 1.环境描述 服务 IP 架构 Oracle 192.168.10.91/92 RAC、主库 Oracle 192.168.10.98 DG备库 达梦 192.168.10.192/192.168.10.193 主备 DMHS 192.168.10.193(DM端) 192.168.10.98(Oracle端) DTS …...

Java面试题:讨论事务的ACID属性,并解释在Java中如何管理事务
事务是数据库管理系统中的一组操作,这些操作要么全部成功,要么全部失败,事务的ACID属性确保了数据库系统的可靠性和一致性。ACID是指: Atomicity(原子性):事务中的所有操作要么全部完成…...

第 5 章理解 ScrollView 并构建 Carousel UI
通过上一章的学习,我相信你现在应该明白如何使用堆栈构建复杂的 UI。当然,在你掌握 SwiftUI 之前,你还需要大量的练习。因此,在深入研究 ScrollView 以使视图可滚动之前,让我们先以一个挑战开始本章。你的任务是创建一个类似于图 1 所示的卡片视图。 …...

MySQL锁、加锁机制(超详细)—— 锁分类、全局锁、共享锁、排他锁;表锁、元数据锁、意向锁;行锁、间隙锁、临键锁;乐观锁、悲观锁
文章目录 一、概述1.1 MySQL锁的由来1.2 锁定义1.3 锁分类 二、共享锁与排他锁2.1 共享锁(S锁)2.2 排他锁(X锁)2.3 MySQL锁的释放 三、全局锁3.1 介绍3.2 语法3.3 特点 四、表级锁4.1 介绍4.2 表锁4.3 元数据锁(Meta D…...

如何在Java中实现文件上传和下载?
如何在Java中实现文件上传和下载? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在现代Web应用程序中,文件上传和下载是常见的功能需求…...

SpringBoot使用滑动窗口限流防止用户重复提交(自定义注解实现)
在你的项目中,有没有遇到用户重复提交的场景,即当用户因为网络延迟等情况把已经提交过一次的东西再次进行了提价,本篇文章将向各位介绍使用滑动窗口限流的方式来防止用户重复提交,并通过我们的自定义注解来进行封装功能。 首先&a…...

ravynOS 0.5.0 发布 - 基于 FreeBSD 的 macOS 兼容开源操作系统
ravynOS 0.5.0 发布 - 基于 FreeBSD 的 macOS 兼容开源操作系统 ravynOS - 一个旨在提供 macOS 的精致性和 FreeBSD 的自由度的操作系统 请访问原文链接:https://sysin.org/blog/ravynos/,查看最新版。原创作品,转载请保留出处。 作者主页…...

韩国面临的本地化挑战
西方文化,尤其是美国电影、音乐和游戏,对韩国也产生了同样大的影响。众所周知,这个国家与外国产品的关系更加开放。然而,游戏在这里仍然受到审查,所以最好避免与朝鲜、日本等有关的分裂性政治主题。否则,你…...

Linux内存从0到1学习笔记(8.17 SMMU Fault调试方法)
写在前面 通过前面的介绍,我们知道了SMMU实际上是一个针对外设的MMU。它作为一个硬件IP被设备执行DMA操作时使用。 再来简单回顾下SMMU的工作流程: 外设 ---> DMA操作 ---> SMMU ---> Memory 也就是说,通常情况下驱动程序会先分配DMA Buffer ---> 然后执行S…...

讲座学习截图——《CAD/CAE/CAM几何引擎-软件概述》(一)
目录 引出CAD/CAE/CAM几何引擎-软件概述 郝建兵CADCAECAM 几何模型内核ACIS 两个老大之一Open CascadeParasolid 两个老大之一Autodesk的内核 总结其他自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重载带参数的按钮触发信号触发信号拓展 lambda表达式…...

鸿蒙开发系统基础能力:【@ohos.hichecker (检测模式)】
检测模式 HiChecker可以作为应用开发阶段使用的检测工具,用于检测代码运行过程中部分易忽略的问题,如应用线程出现耗时调用、应用进程中Ability资源泄露等问题。开发者可以通过日志记录或进程crash等形式查看具体问题并进行修改,提升应用的使…...

WordPress CDN是什么?CDN有什么作用?
您想让您的网站加载速度更快吗? 网站所有者希望网站加载速度快,内容丰富,功能强大,吸引用户。然而,添加这些功能可能会降低网站速度,难以快速向全球用户提供内容。 这就是为什么许多WordPress网站使用 CDN…...

【containerd】Containerd高阶命令行工具nerdctl
前言 对于习惯了使用docker cli的用户来说,containerd的命令行工具ctr使用起来不是很顺手,此时别慌,还有另外一个命令行工具项目nerdctl可供我们选择。 nerdctl是一个与docker cli风格兼容的containerd的cli工具。 nerdctl已经作为子项目加入…...

Spring+SpringMVC+MyBatis整合
目录 1.SSM介绍1.1 什么是SSM?1.2 SSM框架1.2.1 Spring1.2.2 SpringMVC1.2.3 MyBatis 2.SSM框架整合2.1 建库建表2.2 创建工程2.3 pom.xml2.4 log4j.properties2.5 db.properties2.6 applicationContext-dao.xml2.7.applicationContext-tx.xml2.8 applicationContex…...

springboot+vue+mybatis穷游管理系统+PPT+论文+讲解+售后
随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多企业的之中,随之就产生了“基于vue的穷游管理系统”,这样就让基于vue的穷游管理系统更加方便简单。 对于本基于vue的穷游管理系统的设计来说…...

ClickHouse备份方案
ClickHouse备份方案主要包括以下几种方法: 一、使用clickhouse-backup工具: (参考地址:https://blog.csdn.net/qq_43510111/article/details/136570850) **安装与配置:**首先从GitHub获取clickhouse-bac…...

windows启用和禁用内存压缩
windows内存压缩 Windows操作系统的内存压缩是一种通过压缩和解压缩内存页面来减少内存使用量的技术。当系统的内存使用达到一定阈值时,Windows会将不常用的内存页面压缩为一个稳定的压缩文件,以释放更多的内存空间。 内存压缩的主要目的是减少页面交换…...

MATLAB-振动问题:单自由度无阻尼振动系统受迫振动
一、基本理论 二、MATLAB实现 令式(1.3)中A0 2,omega0 30,omega 40,matlab程序如下: clear; clc; close all;A0 2; omega0 30; omega 40; t 0:0.02:5; y A0 * sin( (omega0 - omega) * t /2) .* s…...

示例:WPF中应用DependencyPropertyDescriptor监视依赖属性值的改变
一、目的:开发过程中,经常碰到使用别人的控件时有些属性改变没有对应的事件抛出,从而无法做处理。比如TextBlock当修改了IsEnabled属性我们可以用IsEnabledChanged事件去做对应的逻辑处理,那么如果有类似Background属性改变我想找…...

链家房屋数据爬取与预处理-大数据采集与预处理课程设计
芜湖市链家二手房可视化平台 成品展示 重点说明 1.数据特征数量和名称、数据量 数据特征数量:14; 名称:小区名、价格/万、地区、房屋户型、所在楼层、建筑面积/平方米、户型结构、套内面积、建筑类型、房屋朝向、建筑结构、装修情况、梯户…...

一种502 bad gateway nginx/1.18.0的解决办法
背景:上线的服务突然挂掉了 step1,去后端日志查看,发现并无异常,就是请求无法被接收 step2,查看了nginx的错误日志,发现该文件为空 step3,查看了niginx的运行日志,发现了以下问题 [error] 38#…...

二叉树第一期:树与二叉树的概念
一、树 1.树的定义 与线性表不同,树是一种非线性的数据结构,由N(N>0)个结点组成的具有层次关系的集合;因其形状类似生活中一颗倒挂着的树,故将其数据结构称为树。 2.树的相关概念 根结点 没有前驱的结点,称为根…...

vue跨域问题,请注意你的项目是vue2还是vue3
uniapp跨域设置了,但还是有问题 uniapp设置代理后还是无法请求后端接口vue2项目设置代理vue3项目设置代理 uniapp设置代理后还是无法请求后端接口 如果你在possman,apifox上测试接口都没有问题,但是在hbuild项目中设置代理后,还是…...

大厂晋升学习方法一:海绵学习法
早晨 30 分钟 首先,我们可以把起床的闹钟提前 30 分钟,比如原来 07:30 的闹钟可以改为 07:00。不用担心提前 30 分钟起床会影响休息质量,习惯以后,早起 30 分钟不但不会影响一天的精力,甚至可能反而让人更有精神。早起…...

【ARMv8/v9 GIC 系列 4.2 -- GIC CPU Interface 详细介绍】
文章目录 GIC CPU Interface 介绍CPU Interface 主要寄存器 GIC CPU Interface 介绍 A 系列处理器提供 5个管脚来实现中断,分别是: nIRQ:物理普通中断nFIQ:物理快速中断nVIRQ:虚拟普通中断nVFIQ:虚拟快速…...

小抄 20240619
1 一个人内心充满恐惧的时候,就会开始信仰一个至高的东西来追求道德上的确定感。 然后会向外看,去指责那些自己不敢做但别人做到的,在他看来不道德的事。 2 之前说租房有不可能三角:房租低,离公司近,住着…...