React 之 Redux =》 理解+应用
文章目录
- Redux基础介绍
- 一、概述
- 二、元素组成
- 1. Action(动作)
- 2. Reducer(纯函数)
- 3. Store(仓库)
- 三、原理结构
- 四、场景应用
- 1. 大型复杂的单页应用(SPA)
- 2. 多用户协作的应用
- 3. 数据持久化和缓存管理
- 五、实例
- 1. 简单的计数器应用
- 2. 待办事项列表应用
- Redux 之 React
- 在React中使用Redux
- 一、安装Redux相关库
- 二、创建Redux Store和相关逻辑
- 三、在React组件中使用Redux
- 类组件connect具体应用
- **导出复用原理**
- **实例**
- 1. 安装依赖
- 2. 创建Redux相关文件
- actions.js
- reducers.js
- store.js
- 3. 创建React类组件
- Product.js
- CartItem.js
- Cart.js
- App.js
- 4. 总结
- redux 中间件应用及介绍
Redux基础介绍
一、概述
Redux是一个可预测的JavaScript应用程序状态管理容器。它主要用于JavaScript应用,特别是在React、Angular、Vue等框架中,但也可以与其他视图库一起使用。Redux遵循单向数据流的原则,使得应用的状态变化可预测,方便调试和维护。
二、元素组成
1. Action(动作)
- 定义:是一个包含
type
属性的普通JavaScript对象,用于描述发生了什么事情。type
通常是一个字符串常量,用于唯一标识这个动作。例如:
const ADD_TODO = 'ADD_TODO';
const addTodo = (text) => {return {type: ADD_TODO,payload: text};
}
- 作用:它是改变状态的唯一途径,就像一个“指令”,告诉Redux需要进行什么样的操作。
2. Reducer(纯函数)
- 定义:是一个纯函数,它接收两个参数,当前的
state
(应用的状态)和一个action
。根据action
的type
来决定如何更新state
,并返回新的state
。例如:
const initialState = {todos: []
};
const todoReducer = (state = initialState, action) => {switch (action.type) {case ADD_TODO:return {...state,todos: [...state.todos, {text: action.payload, completed: false}]};default:return state;}
}
- 特点:
- 纯函数特性:给定相同的输入(相同的
state
和action
),总是返回相同的输出。没有副作用,如不会修改传入的参数,不会进行异步操作,也不会直接操作DOM。 - 不可变性:在更新
state
时,应该返回一个新的对象,而不是直接修改原有的state
。这有助于追踪状态的变化,并且在React等视图层中可以更高效地检测组件是否需要重新渲染。
- 纯函数特性:给定相同的输入(相同的
3. Store(仓库)
- 定义:是一个对象,它将
action
和reducer
联系在一起。通过createStore
函数创建(在Redux核心库中)。例如:
import { createStore } from 'redux';
const store = createStore(todoReducer);
- 功能:
- 保存状态:它存储着整个应用的状态树。可以通过
store.getState()
方法获取当前的状态。 - 分发动作:提供
store.dispatch(action)
方法,用于将action
发送给reducer
,从而触发状态的更新。 - 订阅更新:通过
store.subscribe(listener)
方法,可以订阅状态的变化。当状态更新时,会调用listener
函数,通常用于更新UI等操作。
- 保存状态:它存储着整个应用的状态树。可以通过
三、原理结构
Redux的工作流程是单向数据流:
- 动作触发:视图层(如React组件)通过用户交互或者其他事件(例如点击按钮)触发一个
action
。 - 动作分发:这个
action
被store.dispatch()
方法分发到reducer
。 - 状态更新:
reducer
根据传入的action
和当前state
,计算并返回一个新的state
。这个新的state
会替换掉旧的state
存储在store
中。 - 通知订阅者:
store
会通知所有订阅了状态变化的监听器(通过store.subscribe()
注册的函数)。这些监听器通常会更新视图层,使得UI能够反映最新的状态。
四、场景应用
1. 大型复杂的单页应用(SPA)
- 在大型SPA中,应用状态可能会非常复杂,涉及多个模块和组件之间的交互。例如,一个电商单页应用,有商品列表展示、购物车管理、用户登录状态等多个功能模块。
- 商品列表:当用户进行搜索操作时,会触发一个
SEARCH_PRODUCTS
类型的action
,reducer
会根据这个action
更新商品列表的状态。 - 购物车管理:添加商品到购物车会触发
ADD_TO_CART
类型的action
,从购物车移除商品会触发REMOVE_FROM_CART
等动作,这些动作通过reducer
来更新购物车状态。Redux可以很好地管理这些复杂的状态变化,确保每个模块的状态更新是可预测的。
2. 多用户协作的应用
- 考虑一个实时文档编辑应用,多个用户可以同时编辑一个文档。
- 当一个用户输入内容时,会触发
UPDATE_DOCUMENT
类型的action
。Redux可以协调各个用户的操作,通过服务器同步数据,使得每个用户看到的文档状态都是最新的。reducer
会根据这些操作更新文档的内容状态,并且通过store
的订阅机制,及时更新每个用户的视图。
3. 数据持久化和缓存管理
- 对于一些需要离线支持或者频繁请求相同数据的应用。例如,一个新闻阅读应用,它可以使用Redux来管理已缓存的新闻文章。
- 当应用首次加载新闻文章时,会触发
FETCH_ARTICLES
类型的action
,reducer
更新状态来存储获取到的文章列表。如果应用离线,它可以从Redux存储的状态中读取已缓存的文章,提供给用户阅读。同时,当用户手动刷新文章列表或者设置了定时更新时,又会触发新的FETCH_ARTICLES
动作来更新缓存。
五、实例
1. 简单的计数器应用
- 创建Action
// 定义action类型
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// 创建action创建函数
const increment = () => {return {type: INCREMENT};
}
const decrement = () => {return {type: DECREMENT};
}
- 创建Reducer
const initialState = {count: 0
};
const counterReducer = (state = initialState, action) => {switch (action.type) {case INCREMENT:return {...state,count: state.count + 1};case DECREMENT:return {...state,count: state.count - 1};default:return state;}
}
- 创建Store并使用
import { createStore } from 'redux';
const store = createStore(counterReducer);
// 订阅状态变化并更新UI(这里简单打印)
const unsubscribe = store.subscribe(() => {console.log(store.getState().count);
});
// 分发动作
store.dispatch(increment());
store.dispatch(increment());
store.dispatch(decrement());
// 取消订阅
unsubscribe();
2. 待办事项列表应用
- 创建Action
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';
const addTodo = (text) => {return {type: ADD_TODO,payload: text};
}
const toggleTodo = (index) => {return {type: TOGGLE_TODO,payload: index};
}
- 创建Reducer
const initialState = {todos: []
};
const todoReducer = (state = initialState, action) => {switch (action.type) {case ADD_TODO:return {...state,todos: [...state.todos, {text: action.payload, completed: false}]};case TOGGLE_TODO:const newTodos = [...state.todos];newTodos[action.payload].completed =!newTodos[action.payload].completed;return {...state,todos: newTodos};default:return state;}
}
- 创建Store并使用
const store = createStore(todoReducer);
// 订阅状态变化并更新UI(这里简单打印)
const unsubscribe = store.subscribe(() => {console.log(store.getState().todos);
});
// 分发动作
store.dispatch(addTodo("Buy milk"));
store.dispatch(addTodo("Read a book"));
store.dispatch(toggleTodo(0));
unsubscribe();
Redux 之 React
在React中使用Redux
一、安装Redux相关库
- 首先需要安装
redux
和react-redux
库。- 如果使用npm,可以在项目目录下的终端中运行以下命令:
npm install redux react-redux
- 如果使用yarn,则运行:
yarn add redux react-redux
二、创建Redux Store和相关逻辑
- 定义Actions(动作)
- 在React项目中,通常在一个单独的文件(如
actions.js
)中定义动作。例如,对于一个简单的计数器应用,定义增加和减少计数的动作:
// actions.js export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; export const increment = () => {return {type: INCREMENT}; }; export const decrement = () => {return {type: DECREMENT}; };
- 在React项目中,通常在一个单独的文件(如
- 创建Reducers(纯函数)
- 同样在一个单独的文件(如
reducers.js
)中创建。以计数器应用为例,创建一个简单的reducer来处理计数状态的更新:
// reducers.js import { INCREMENT, DECREMENT } from './actions'; const initialState = {count: 0 }; const counterReducer = (state = initialState, action) => {switch (action.type) {case INCREMENT:return {...state,count: state.count + 1};case DECREMENT:return {...state,count: state.count - 1};default:return state;} }; export default counterReducer;
- 同样在一个单独的文件(如
- 创建Store(仓库)
- 在项目的入口文件(如
index.js
)或者专门的store.js
文件中创建store。例如:
// store.js import { createStore } from 'redux'; import counterReducer from './reducers'; const store = createStore(counterReducer); export default store;
- 在项目的入口文件(如
三、在React组件中使用Redux
- 使用
Provider
组件包裹根组件- 在
index.js
文件中,将整个React应用包裹在Provider
组件内,使得应用中的所有组件都可以访问Redux store。Provider
是react - redux
库提供的组件。
import React from 'react'; import ReactDOM from 'react - dom'; import App from './App'; import { Provider } from 'react - redux'; import store from './store'; ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById('root') );
- 在
- 在组件中连接Redux(使用
connect
函数)- 功能性组件(使用
useSelector
和useDispatch
)- 对于功能性组件,可以使用
react - redux
提供的useSelector
和useDispatch
钩子函数来获取状态和分发动作。例如,在一个计数器组件中:
import React from 'react'; import { useSelector, useDispatch } from 'react - redux'; import { increment, decrement } from './actions'; const Counter = () => {const count = useSelector((state) => state.count);const dispatch = useDispatch();return (<div><p>Count: {count}</p><button onClick={() => dispatch(increment())}>Increment</button><button onClick={() => dispatch(decrement())}>Decrement</button></div>); }; export default Counter;
- 对于功能性组件,可以使用
- 类组件(使用
connect
函数)- 对于类组件,使用
connect
函数来连接Redux。例如,将上面的计数器组件改写为类组件:
import React, { Component } from 'react'; import { connect } from 'react - redux'; import { increment, decrement } from './actions'; class Counter extends Component {render() {const { count, increment, decrement } = this.props;return (<div><p>Count: {count}</p><button onClick={increment}>Increment</button><button onClick={decrement}>Decrement</button></div>);} } const mapStateToProps = (state) => ({count: state.count }); const mapDispatchToProps = {increment,decrement }; export default connect(mapStateToProps, mapDispatchToProps)(Counter);
- 对于类组件,使用
mapStateToProps
函数- 这个函数用于将Redux store中的状态映射到组件的
props
中。它接收整个Redux状态树作为参数,返回一个对象,对象中的属性会被合并到组件的props
中。例如,在上面的类组件中,mapStateToProps
将state.count
映射为组件的count
属性。
- 这个函数用于将Redux store中的状态映射到组件的
mapDispatchToProps
函数(或对象)- 这个函数(或对象)用于将动作创建函数映射到组件的
props
中,使得组件可以通过props
来分发动作。在类组件的例子中,mapDispatchToProps
是一个对象,它将increment
和decrement
动作创建函数直接作为属性,这些属性会被添加到组件的props
中,从而可以在组件中通过this.props.increment
和this.props.decrement
来分发动作。在功能性组件中,useDispatch
钩子函数返回的dispatch
函数用于手动分发动作,更加灵活。
- 这个函数(或对象)用于将动作创建函数映射到组件的
- 功能性组件(使用
类组件connect具体应用
导出复用原理
connect
函数的作用机制- 在React - Redux中,
connect
函数是一个高阶函数,用于将React组件与Redux的store
连接起来。它接收两个参数:mapStateToProps
和mapDispatchToProps
(这两个参数也可以是函数或者对象,用于不同的映射方式)。 mapStateToProps
原理:这个函数用于将Reduxstore
中的状态映射到组件的props
中。它会在store
状态发生变化时被调用,每次调用都会重新计算返回的对象。返回对象中的属性会作为props
传递给组件。例如,如果mapStateToProps
返回{ count: state.count }
,那么组件就会通过props.count
来访问Redux中的count
状态。mapDispatchToProps
原理:这个函数(或对象)用于将Redux中的action
创建函数映射到组件的props
中。当它是一个函数时,接收dispatch
作为参数,返回一个对象,对象中的属性是action
创建函数,这些函数内部会调用dispatch
来分发action
。当它是一个对象时,对象中的属性直接就是action
创建函数,connect
函数会自动将它们绑定到dispatch
上,这样组件就可以通过props
来调用这些action
创建函数。
- 在React - Redux中,
- 组件复用原理
- 当一个通过
connect
函数连接了Redux的组件被导出后,它可以在多个地方被复用。因为mapStateToProps
和mapDispatchToProps
的映射关系是基于组件的使用场景和Redux的store
结构来定义的,所以只要Reduxstore
的结构和组件所需的状态及action
保持一致,组件就可以在不同的地方复用。例如,一个显示用户信息的组件,它通过mapStateToProps
获取用户状态,通过mapDispatchToProps
获取更新用户信息的action
函数,只要在其他地方也有相同的Reduxstore
结构和对用户信息的操作需求,这个组件就可以直接复用。
- 当一个通过
实例
1. 安装依赖
确保项目中安装了 redux
和 react-redux
:
npm install redux react-redux
2. 创建Redux相关文件
actions.js
定义购物车相关的 action
类型和 action
创建函数。
// actions.js
export const ADD_ITEM = 'ADD_ITEM';
export const REMOVE_ITEM = 'REMOVE_ITEM';
export const INCREMENT_QUANTITY = 'INCREMENT_QUANTITY';
export const DECREMENT_QUANTITY = 'DECREMENT_QUANTITY';export const addItem = (product) => ({type: ADD_ITEM,payload: product
});export const removeItem = (productId) => ({type: REMOVE_ITEM,payload: productId
});export const incrementQuantity = (productId) => ({type: INCREMENT_QUANTITY,payload: productId
});export const decrementQuantity = (productId) => ({type: DECREMENT_QUANTITY,payload: productId
});
reducers.js
创建购物车的 reducer
,处理各种 action
对购物车状态的更新。
// reducers.js
import { ADD_ITEM, REMOVE_ITEM, INCREMENT_QUANTITY, DECREMENT_QUANTITY } from './actions';const initialState = {cart: []
};const cartReducer = (state = initialState, action) => {switch (action.type) {case ADD_ITEM:return {...state,cart: [...state.cart, {...action.payload,quantity: 1}]};case REMOVE_ITEM:return {...state,cart: state.cart.filter(item => item.id!== action.payload)};case INCREMENT_QUANTITY:return {...state,cart: state.cart.map(item =>item.id === action.payload? {...item,quantity: item.quantity + 1} : item)};case DECREMENT_QUANTITY:return {...state,cart: state.cart.map(item =>item.id === action.payload && item.quantity > 1? {...item,quantity: item.quantity - 1} : item)};default:return state;}
};export default cartReducer;
store.js
创建Redux的 store
。
// store.js
import { createStore } from'redux';
import cartReducer from './reducers';const store = createStore(cartReducer);export default store;
3. 创建React类组件
Product.js
定义商品展示组件,该组件可以触发添加商品到购物车的操作。
// Product.js
import React, { Component } from'react';
import { connect } from'react - redux';
import { addItem } from './actions';class Product extends Component {render() {const { product, addItem } = this.props;return (<div><h3>{product.name}</h3><p>{product.price}</p><button onClick={() => addItem(product)}>Add to Cart</button></div>);}
}const mapDispatchToProps = {addItem
};export default connect(null, mapDispatchToProps)(Product);
CartItem.js
定义购物车中商品项的展示组件,该组件可以触发移除商品、增加和减少商品数量的操作。
// CartItem.js
import React, { Component } from'react';
import { connect } from'react - redux';
import { removeItem, incrementQuantity, decrementQuantity } from './actions';class CartItem extends Component {render() {const { item, removeItem, incrementQuantity, decrementQuantity } = this.props;return (<div><p>{item.name}</p><p>Quantity: {item.quantity}</p><button onClick={() => incrementQuantity(item.id)}>Increment</button><button onClick={() => decrementQuantity(item.id)}>Decrement</button><button onClick={() => removeItem(item.id)}>Remove</button></div>);}
}const mapDispatchToProps = {removeItem,incrementQuantity,decrementQuantity
};export default connect(null, mapDispatchToProps)(CartItem);
Cart.js
定义购物车展示组件,复用 CartItem
组件展示购物车中的所有商品。
// Cart.js
import React, { Component } from'react';
import { connect } from'react - redux';
import CartItem from './CartItem';class Cart extends Component {render() {const { cart } = this.props;return (<div><h2>Shopping Cart</h2>{cart.map(item => (<CartItem key={item.id} item={item} />))}</div>);}
}const mapStateToProps = (state) => ({cart: state.cart
});export default connect(mapStateToProps)(Cart);
App.js
在 App
组件中复用 Product
和 Cart
组件,展示商品列表和购物车。
// App.js
import React, { Component } from'react';
import { Provider } from'react - redux';
import store from './store';
import Product from './Product';
import Cart from './Cart';const products = [{ id: 1, name: 'Product 1', price: 10 },{ id: 2, name: 'Product 2', price: 15 }
];class App extends Component {render() {return (<Provider store = {store}><div><h1>Redux Shopping Cart Example</h1><div><h2>Products</h2>{products.map(product => (<Product key={product.id} product={product} />))}</div><Cart /></div></Provider>);}
}export default App;
4. 总结
在上述代码中,Product
组件和 CartItem
组件都通过 connect
函数与Redux建立连接,能够触发Redux中的方法(action
)。Cart
组件复用了 CartItem
组件来展示购物车中的商品。整个应用通过 Provider
组件将Redux的 store
提供给所有子组件,实现了状态管理和组件间的交互。
redux 中间件应用及介绍
- Redux-Thunk
- 作用:
- 用于处理异步操作。它允许
action
创建函数返回一个函数,而不是一个普通的action
对象。这个返回的函数可以接收dispatch
和getState
作为参数,从而在函数内部执行异步操作(如网络请求),并根据异步操作的结果来分发action
。
- 用于处理异步操作。它允许
- 实例:
- 假设我们要从一个API获取用户数据并更新Redux状态。
- 首先,定义
action
类型和action
创建函数:// actions.js const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS'; const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE'; const fetchUser = () => {return async (dispatch) => {try {const response = await fetch('https://example.com/api/user');const userData = await response.json();dispatch({type: FETCH_USER_SUCCESS,payload: userData});} catch (error) {dispatch({type: FETCH_USER_FAILURE,payload: error.message});}}; };
- 然后,创建
reducer
来处理action
:// reducers.js const initialState = {user: null,error: null }; const userReducer = (state = initialState, action) => {switch (action.type) {case FETCH_USER_SUCCESS:return {...state,user: action.payload};case FETCH_USER_FAILURE:return {...state,error: action.payload};default:return state;} }; export default userReducer;
- 最后,在创建
store
时应用redux - thunk
中间件:// store.js import { createStore, applyMiddleware } from 'redux'; import thunkMiddleware from 'redux - thunk'; import userReducer from './reducers'; const store = createStore(userReducer,applyMiddleware(thunkMiddleware) );
- 作用:
- Redux-Saga
- 作用:
- 也是用于处理异步操作,它基于
Generator
函数。Redux - Saga
将异步操作看作是可以被暂停和恢复的一系列步骤,通过Generator
函数的yield
关键字来暂停Saga
的执行,等待异步操作完成后再恢复执行。这样可以更方便地处理复杂的异步流程,如并发请求、轮询等。
- 也是用于处理异步操作,它基于
- 实例:
- 同样是获取用户数据的例子。
- 首先,定义
Saga
函数:// sagas.js import { call, put, takeEvery } from 'redux - saga/effects'; const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS'; const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE'; function* fetchUserSaga() {try {const response = yield call(fetch, 'https://example.com/api/user');const userData = yield call([response, 'json']);yield put({type: FETCH_USER_SUCCESS,payload: userData});} catch (error) {yield put({type: FETCH_USER_FAILURE,payload: error.message});} } function* rootSaga() {yield takeEvery('FETCH_USER', fetchUserSaga); } export default rootSaga;
- 然后,创建
reducer
(和上面Redux - Thunk
例子中的reducer
类似):// reducers.js const initialState = {user: null,error: null }; const userReducer = (state = initialState, action) => {switch (action.type) {case FETCH_USER_SUCCESS:return {...state,user: action.payload};case FETCH_USER_FAILURE:return {...state,error: action.payload};default:return state;} }; export default userReducer;
- 最后,在创建
store
时应用Redux - Saga
中间件:// store.js import { createStore, applyMiddleware } from 'redux'; import createSagaMiddleware from 'redux - saga'; import userReducer from './reducers'; import rootSaga from './sagas'; const sagaMiddleware = createSagaMiddleware(); const store = createStore(userReducer,applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga);
- 作用:
- Redux - Logger
- 作用:
- 用于日志记录,它可以在
action
被分发、reducer
处理action
以及状态更新的过程中记录相关信息。这对于调试Redux应用非常有帮助,可以清楚地看到action
的流向和状态的变化情况。
- 用于日志记录,它可以在
- 实例:
- 定义
logger
中间件:// loggerMiddleware.js const loggerMiddleware = (store) => (next) => (action) => {console.log('dispatching', action);const result = next(action);console.log('next state', store.getState());return result; }; export default loggerMiddleware;
- 在创建
store
时应用logger
中间件:// store.js import { createStore, applyMiddleware } from 'redux'; import loggerMiddleware from './loggerMiddleware'; import rootReducer from './reducers'; const store = createStore(rootReducer,applyMiddleware(loggerMiddleware) );
- 当
action
被分发时,例如在一个计数器应用中:// actions.js const INCREMENT = 'INCREMENT'; const increment = () => ({type: INCREMENT });
// counterReducer.js const initialState = {count: 0 }; const counterReducer = (state = initialState, action) => {switch (action.type) {case INCREMENT:return {...state,count: state.count + 1};default:return state;} }; export default counterReducer;
// index.js import React from 'react'; import ReactDOM from 'react - dom'; import { Provider } from 'react - redux'; import store from './store'; import Counter from './Counter'; ReactDOM.render(<Provider store={store}><Counter /></Provider>,document.getElementById('root') );
- 当点击按钮触发
increment
动作时,logger
中间件会在控制台打印出分发的action
({type: 'INCREMENT'}
)以及更新后的状态({count: 1}
等)。
- 当点击按钮触发
- 定义
- 作用:
相关文章:
React 之 Redux =》 理解+应用
文章目录 Redux基础介绍一、概述二、元素组成1. Action(动作)2. Reducer(纯函数)3. Store(仓库) 三、原理结构四、场景应用1. 大型复杂的单页应用(SPA)2. 多用户协作的应用3. 数据持…...
生成excel文件(有备注和表头的情况)
要使用 Java 导出 Excel 文件,并且通过 ExcelProperty 注解进行列的映射,可以利用 EasyExcel 库。EasyExcel 是阿里巴巴开源的一款高性能 Excel 读写工具,它支持通过注解将类与 Excel 的列进行映射,简化了 Excel 操作的复杂性。 …...
Docker 安装全攻略:从入门到上手
Docker 安装全攻略:从入门到上手 在当今的软件开发与部署领域,Docker 已经成为了一项不可或缺的关键技术。它能够将应用程序及其依赖项打包成轻量级、可移植的容器,极大地简化了开发、测试和部署的流程。本文将详细讲解在不同操作系统下 Doc…...
@Scheduled注解的使用-SpringBoot-Springtask
Scheduled 注解是 Spring 框架中用于定时任务调度的核心注解之一。通过 Scheduled 注解,开发者可以非常方便地在 Spring 应用程序中定义和配置各种定时任务,包括固定速率执行、固定延迟执行、cron 表达式执行等。本文将详细讲解 Scheduled 注解的各个方面…...
Elasticsearch:使用 Ollama 和 Go 开发 RAG 应用程序
作者:来自 Elastic Gustavo Llermaly 使用 Ollama 通过 Go 创建 RAG 应用程序来利用本地模型。 关于各种开放模型,有很多话要说。其中一些被称为 Mixtral 系列,各种规模都有,而一种可能不太为人所知的是 openbiollm,这…...
Linux 下 Mamba 环境安装踩坑问题汇总(重置版)
导航 安装教程导航 Mamba 及 Vim 安装问题参看本人博客:Mamba 环境安装踩坑问题汇总及解决方法(初版)Linux 下Mamba 及 Vim 安装问题参看本人博客:Mamba 环境安装踩坑问题汇总及解决方法(重置版)Windows …...
(免费送源码)计算机毕业设计原创定制:Java+springboot+MySQL springboot 线上线下一体化的宠物交易
摘 要 网络发布信息有其突出的优点,即信息量大,资源丰富,更新速度快等,很符合人们希望以捷、便利的方式获得最多最有效信息的要求。本系统就是一个线上线下一体化的宠物交易,为商家提供一个信息发布的平台࿰…...
【Rust自学】7.4. use关键字 Pt.2 :重导入与换国内镜像源教程
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 7.4.1. 使用pub use重新导入名称 使用use将路径导入作用域内后。该名称在词作用域内是私有的。 以上一篇文章的代码为例: m…...
自动生成关于软件程序开发的100个文件并可提供下载入口
创建一个包含100个关于软件程序开发的文件并提供下载入口是一个庞大的任务,因为这需要编写大量的代码、文档和示例。不过,我可以提供一个大致的框架和指导,帮助你生成这些文件,并说明如何设置下载入口。 文件生成思路 编程语言文…...
Linux下基本指令
一、什么是指令 指令本质是可执行程序,在执行指令前,先在系统中查找对应的指令。在Linux系统中指令存在于/usr/bin/路径下 二、ls 指令 1、语法 ls [选项][目录或文件] 2、功能 对于目录,该命令列出该目录下的所有子目录与文件。 对于文…...
2024-12-25-sklearn学习(20)无监督学习-双聚类 料峭春风吹酒醒,微冷,山头斜照却相迎。
文章目录 sklearn学习(20) 无监督学习-双聚类1 Spectral Co-Clustering1.1 数学公式 2 Spectral Biclustering2.1 数学表示 3 Biclustering 评价 sklearn学习(20) 无监督学习-双聚类 文章参考网站: https://sklearn.apachecn.org/ 和 https://scikit-learn.org/sta…...
编程考古-传奇的开始Delphi(下)含所有版本.iso
概览 Delphi 的最新版本,即 Delphi 12,勾勒出了自公司创立以来的一条进化之路。该平台不断通过提升开发者生产力、扩展其支持的平台范围以及引入前沿技术来实现自我完善。作为 Embarcadero 提供的主要快速应用开发(RAD)环境&…...
集合stream
1.Collection集合 1.1数组和集合的区别【理解】 相同点 都是容器,可以存储多个数据 不同点 数组的长度是不可变的,集合的长度是可变的 数组可以存基本数据类型和引用数据类型 集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类 1.2集合类体系结构【理解】…...
Xshell 和 Xftp 更新提示问题的解决方法及分析
Xshell 和 Xftp 更新提示问题的解决方法及分析 在个人使用 Xshell 和 Xftp 的过程中,通过官网注册使用一段时间后,往往会遇到这样的问题:软件提示“要继续使用此程序,你必须应用最新的更新或使用新版本”。对于那些觉得更新比较麻…...
Docker安装MongoDB
Docker安装MongoDB 1、拉取镜像2、创建容器3、启动容器4、进入容器内部5、进入admin数据库6、添加管理员,其拥有管理用户和角色的权限7、进行认证8、通过admin添加普通用户 1、拉取镜像 docker pull mongo:4.0.32、创建容器 docker create --name mongodb-server …...
解锁自动化新高度,zTasker v2.0全方位提升效率
zTasker 是一款集强大功能与高效操作于一体的自动化任务管理软件,以其简单直观的设计和一键完成操作的特性深受用户喜爱。软件体积小巧,运行速度极快,支持超过 100 种不同的任务类型,并提供 30 多种定时或条件触发方式,…...
Windows Server 安装 MySQL 8.0 详细指南
文章目录 Windows Server 安装 MySQL 8.0 详细指南准备工作安装步骤1. 解压安装包2. 初始化数据目录3. 安装 MySQL 服务4. 启动 MySQL 服务 MySQL 配置文件 (my.ini)5. 设置 root 密码6. 配置远程访问 安全建议常见问题排查性能优化提示结语 👉洛秋资源小站 Windows…...
uniapp小程序使用webview 嵌套 vue 项目
uniapp小程序使用webview 嵌套 vue 项目 小程序中发送 <web-view :src"urlSrc" message"handleMessage"></web-view>export default {data() {return {urlSrc: "",};},onLoad(options) {// 我需要的参数比较多 所以比较臃肿// 获取…...
高效搭建Nacos:实现微服务的服务注册与配置中心
一、关于Nacos 1.1 简介 Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一款动态服务发现、配置管理和服务管理平台。它旨在帮助开发者更轻松地构建、部署和管理分布式系统,特别是在微服务架构中。Nacos 提供了简单易用…...
JavaScript 实现动态产品展示网页
JavaScript 实现动态产品展示网页 1. HTML 页面结构2. CSS 样式设计3. JavaScript 实现功能功能总结 本文设计了一个基于 JavaScript 的动态产品展示网页案例,核心功能包括: 动态产品分类过滤:通过点击分类按钮,仅显示属于该分类…...
小程序配置文件 —— 13 全局配置 - window配置
全局配置 - window配置 这里讲解根目录 app.json 中的 window 字段,window 字段用于设置小程序的状态栏、导航条、标题、窗口背景色; 状态栏:顶部位置,有网络信号、时间信息、电池信息等;导航条:有一个当…...
【小程序】wxss与rpx单位以及全局样式和局部样式
目录 WXSS 1. 什么是 WXSS 2. WXSS 和 CSS 的关系 rpx 1. 什么是 rpx 尺寸单位 2. rpx 的实现原理 3. rpx 与 px 之间的单位换算* 样式导入 1. 什么是样式导入 2. import 的语法格式 全局样式和局部样式 1. 全局样式 2. 局部样式 WXSS 1. 什么是 WXSS WXSS (We…...
矩阵的因子分解1-奇异值分解
文章目录 矩阵的因子分解1-奇异值分解求法归纳例1. 对矩阵 A ( 0 1 − 1 0 0 2 1 0 ) A \begin{pmatrix} 0 & 1 \\ -1 & 0 \\ 0 & 2 \\ 1 & 0 \end{pmatrix} A 0−1011020 进行奇异值分解1. 计算 A H A A^H A AHA 的特征值和特征向量2. 将奇异值按…...
Hive其十,优化和数据倾斜
目录 Hive优化 1、开启本地模式 2、explain分析SQL语句 3、修改Fetch操作 4、开启hive的严格模式【提高了安全性】 5、JVM重用 6、分区、分桶以及压缩 7、合理设置map和reduce的数量 合理设置map数量: 设置合理的reducer的个数 8、设置并行执行 9、CBO优…...
云原生后端开发(一)
云原生后端开发 云原生(Cloud-Native)是指一种构建和运行应用程序的方式,它充分利用了云计算的特点,比如弹性伸缩、自动化部署、容器化等。在云原生的架构下,后端应用通常具备高度可扩展、可维护、易于自动化管理的特…...
Python常用模块详解:从操作系统接口到日志记录
Python常用模块详解:从操作系统接口到日志记录 1. os模块:操作系统接口主要功能示例 2. io模块:流操作主要功能示例 3. time模块:时间操作主要功能示例 4. argparse模块:命令行参数解析主要功能示例 5. logging模块&am…...
修改成清华镜像源解决Anaconda报The channel is not accessible源通道不可用问题
修改成清华镜像源解决Anaconda报The channel is not accessible源通道不可用问题 最近在通过pycharm开发python程序,引用anaconda环境建立虚拟环境时报错,报UnavailableInvalidChannel: The channel is not accessible or is invalid.应该是镜像源访问通…...
Python之Web开发
一、基本概念 Web开发是指创建和维护网站或Web应用的过程。一个典型的Web应用包括前端(客户端)和后端(服务器端)。前端负责用户界面的设计和交互,而后端则处理业务逻辑、数据存储和与数据库的通信。Python作为一门功能…...
CDN如何抵御DDoS攻击
一、DDoS攻击的定义 DDoS(Distributed Denial of Service,分布式拒绝服务)攻击是一种常见且破坏性较大的网络攻击方式。攻击者通过控制大量分布在全球各地的受感染设备(称为“僵尸网络”),同时向目标服务器…...
基于进程信号量的多线程同步机制研究与实现
1 信号量 1.1 原理与概念 信号量机制本质是对于资源的预订操作,线程或者进程预订了之后,确保未来有一段时间,资源是属于我的。 对于预订资源,会有一个最小单位,资源都是以这个最小单位为整体被使用的。 信号量需要做…...
七、队列————相关概念详解
队列————相关概念详解 前言一、队列1.1 队列是什么?1.2 队列的类比 二、队列的常用操作三、队列的实现3.1 基于数组实现队列3.1.1 基于环形数组实现的队列3.1.2 基于动态数组实现的队列 3.2 基于链表实现队列 四、队列的典型应用总结 前言 本篇文章,我们一起来…...
钉钉h5微应用鉴权配置客户端 API 鉴权步骤
这里记录一下使用的钉钉h5微应用 配置客户端 API 鉴权的内容 注意不是所有的都功能都需要鉴权。 先要引入钉钉环境 见下链接 https://blog.csdn.net/KLS_CSDN/article/details/144794982?spm1001.2014.3001.5501 引入鉴权代码到前端页面并配置以下参数: dd.con…...
04.HTTPS的实现原理-HTTPS的混合加密流程
04.HTTPS的实现原理-HTTPS的混合加密流程 简介1. 非对称加密与对称加密2. 非对称加密的工作流程3. 对称加密的工作流程4. HTTPS的加密流程总结 简介 主要讲述了HTTPS的加密流程,包括非对称加密和对称加密两个阶段。首先,客户端向服务器发送请求…...
Python中构建终端应用界面利器——Blessed模块
在现代开发中,命令行应用已经不再仅仅是一个简单的文本输入输出工具。随着需求的复杂化和用户体验的重视,终端界面也逐渐成为一个不可忽视的设计环节。 如果你曾经尝试过开发终端UI,可能对传统的 print() 或者 input() 函数感到不满足&#…...
【Python】 基于Python实现日志聚合与分析工具:利用Logstash与Fluentd构建高效分布式日志系统
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在分布式系统中,日志数据的生成速度和数量呈指数级增长,传统的日志管理方式已无法满足现代企业对实时性、可扩展性和高效性的需求。本文深…...
汽车网络安全基线安全研究报告
一、引言 随着汽车行业朝着智能网联方向飞速发展,汽车网络安全已成为保障用户安全和行业健康发展的关键要素。本报告将深入探讨汽车网络安全相关内容,以及国际、国内重要的汽车网络安全标准基线和相应防护措施等内容。 二、汽车网络安全的重要性 &…...
[pdf、epub]260道《软件方法》强化自测题业务建模需求分析共216页(202412更新)
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 260道《软件方法》强化自测题业务建模需求分析共216页(202412更新) 已上传到本CSDN账号的资源 如果下载不到,也可以访问以下链接: ht…...
工业4.0和MES(制造执行系统)方案(附实践资料)
工业4.0和MES(制造执行系统)方案是智能制造领域中的关键组成部分,它们共同推动着制造业的数字化转型。以下是工业4.0和MES方案的一些核心要点: 智能制造背景: 工业4.0是第四次工业革命,它结合了信息通信技术…...
机器视觉中的单线程、多线程与跨线程:原理与应用解析
在机器视觉应用中,程序的运行效率直接影响到系统的实时性和稳定性。随着任务复杂度的提高,单线程处理往往无法满足高性能需求,多线程技术因此被广泛应用。此外,跨线程操作(如在多线程中更新界面或共享资源)…...
性能测试瓶颈:CPU 问题的深度分析和调优
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 我们做性能测试的时候,除了使用工具编写脚本并执行之外,最核心的工作就是做性能测试结果分析和问题调优。然后在做性能测试的时候…...
云手机与Temu矩阵:跨境电商运营新引擎
云手机与 Temu 矩阵结合的基础 云手机技术原理 云手机基于先进的 ARM 虚拟化技术,在服务器端运行 APP。通过在服务器上利用容器虚拟化软件技术,能够虚拟出多个独立的手机操作系统实例,每个实例等同于一部单独的手机,可独立运行各…...
Oracle考试多少分算通过?
OCP和OCM认证的考试及格分数并不是固定的,而是根据考试的难度和考生的整体表现来确定。对于OCP认证,考生需要全面掌握考试要求的知识和技能,并在考试中表现出色才有可能通过。而对于OCM认证,考生则需要在每个模块中都达到一定的水…...
【UE5.3.2】安装metahuman插件
Unable to find plugin ‘MetaHuman’报错 Unable to find plugin MetaHuman (referenced via RPect_5_3.uproject). Install it and try again, or remove it from the required plugin list. 10>Microsoft.MakeFile.Targets(44,5): Error MSB3073 :...
python lambda函数用法
在Python中,lambda函数是一种用于创建匿名函数的简便方式。它允许你快速定义一个简单的函数,而不需要使用传统的def语句。lambda函数通常用于一次性的操作或作为参数传递给其他函数。 lambda函数的语法: lambda 参数1, 参数2, ... : 表达式l…...
acitvemq AMQP:因为消息映射策略配置导致的MQTT接收JMS消息乱码问题 x-opt-jms-dest x-opt-jms-msg-type
使用ActiveMQ(5.14.5)作消息系统服务的场景下, 当我用Apache Qpid Proton发送消息(使用AMQP协议)发送JMS消息,用Paho MQTT接收消息的时候, 收到的消息前面总是有一串乱码,大概就是这样: 4Sp?AS…...
ida的使用
一.ida的基本设置 在IDA的安装根目录下有许多文件夹,各个文件夹存储不同的内容 1.目录结构 cfg:包含各种配置文件,基本IDA配置文件ida.cfg,GUI配置文件idagui.cfg,文本模式用户界面配置文件idatui.cfg, idc:包含…...
archery docker安装
#下载Archery-1.11.3.tar.gz https://codeload.github.com/hhyo/Archery/tar.gz/refs/tags/v1.11.3 cd /root tar -zxvf Archery-1.11.3.tar.gz cd /root/Archery-1.11.3/src/docker-compose #启动 docker compose -f docker-compose.yml up -d#表结构初始化 docker exec -ti a…...
【zookeeper核心源码解析】第四课:客户端与服务端读写的io核心流程
系列文章目录 【zookeeper核心源码解析】第一课:zk启动类核心流程序列图 【zookeeper核心源码解析】第二课:俯瞰QuorumPeer启动核心流程,实现选举关键流程 【zookeeper核心源码解析】第三课:leader与follower何时开始同步&#…...
影刀进阶指令 | Kimi (对标ChatGPT)
文章目录 影刀进阶指令 | Kimi (对标ChatGPT)一. 需求二. 流程三. 实现3.1 流程概览3.2 流程步骤讲解1\. 确定问题2\. 填写问题并发送3\. 检测答案是否出完 四. 运维 影刀进阶指令 | Kimi (对标ChatGPT) 简单讲讲RPA调用kimi实现…...
Linux第99步_Linux之点亮LCD
主要学习如何在Linux开发板点亮屏,以及modetest命令的实现。 很多人踩坑,我也是一样。关键是踩坑后还是实现不了,这样的人确实很多,从群里可以知道。也许其他人没有遇到这个问题,我想是他运气好。 1、修改设备树 1)、…...