react学习笔记4——React UI组件库与redux
流行的开源React UI组件库
material-ui(国外)
- 官网: http://www.material-ui.com/#/
- github: GitHub - mui/material-ui: Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
ant-design(国内蚂蚁金服)
- 官网: Ant Design - 一套企业级 UI 设计语言和 React 组件库
- Github: GitHub - ant-design/ant-design: An enterprise-class UI design language and React UI library
redux
redux理解
学习文档
- 英文文档: Redux - A JS library for predictable and maintainable global state management | Redux
- 中文文档: Redux | Redux 中文文档
- Github: GitHub - reduxjs/redux: A JS library for predictable global state management
redux是什么
- redux是一个专门用于做状态管理的JS库(不是react插件库)。
- 它可以用在react, angular, vue等项目中, 但基本与react配合使用。
- 作用: 集中式管理react应用中多个组件共享的状态。
什么情况下需要使用redux
- 某个组件的状态,需要让其他组件可以随时拿到(共享)。
- 一个组件需要改变另一个组件的状态(通信)。
- 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
redux工作流程
redux的三个核心概念
action
- 动作的对象
- 包含2个属性
- type:标识属性, 值为字符串, 唯一, 必要属性
- data:数据属性, 值类型任意, 可选属性
- 例子:{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }
reducer
- 用于初始化状态、加工状态。
- 加工时,根据旧的state和action, 产生新的state的纯函数。
store
- 将state、action、reducer联系在一起的对象
- 如何得到此对象?
import {createStore} from 'redux'
import reducer from './reducers'
const store = createStore(reducer)
- 此对象的功能?
1.getState(): 得到state
2.dispatch(action): 分发action, 触发reducer调用, 产生新的state
3.subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
redux的核心API
createstore()
作用:创建包含指定reducer的store对象
store对象
- 作用: redux库最核心的管理对象
- 它内部维护着:
1.state
2.reducer
3.核心方法:
1.getState()
2.dispatch(action)
3.subscribe(listener)
4.具体编码:
1.store.getState()
2.store.dispatch({type:'INCREMENT', number})
3.store.subscribe(render)
applyMiddleware()
作用:应用上基于redux的中间件(插件库)
combineReducers()
作用:合并多个reducer函数
使用redux编写应用
redux异步编程
理解:
- redux默认是不能进行异步处理的,
- 某些时候应用中需要在redux中执行异步任务(ajax, 定时器)
使用异步中间件
npm install --save redux-thunk
react-redux
react-redux模型
理解
- 一个react插件库
- 专门用来简化react应用中使用redux
react-Redux将所有组件分成两大类
- UI组件
- 容器组件
1.负责管理数据和业务逻辑,不负责UI的呈现
2.使用 Redux 的 API
3.一般保存在containers文件夹下
相关API
- Provider:让所有组件都可以得到state数据
2.connect:用于包装 UI 组件生成容器组件
3.mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性
4.mapDispatchToProps:将分发action的函数转换为UI组件的标签属性
使用上redux调试工具
安装chrome浏览器插件
下载工具依赖包
npm install --save-dev redux-devtools-extension
redux插件常用部分
纯函数和高阶函数
纯函数
- 一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)
- 必须遵守以下一些约束
-
- 不得改写参数数据
- 不会产生任何副作用,例如网络请求,输入和输出设备
- 不能调用Date.now()或者Math.random()等不纯的方法
-
- redux的reducer函数必须是一个纯函数
高阶函数
- 理解: 一类特别的函数
1.情况1: 参数是函数
2.情况2: 返回是函数
2.常见的高阶函数:
1.定时器设置函数
2.数组的forEach()/map()/filter()/reduce()/find()/bind()
3.promise
4.react-redux中的connect函数
3.作用: 能实现更加动态, 更加可扩展的功能
相关代码:
主要文件:index.js, App.jsx, redux文件, components文件, pages文件,有相同代码
纯react版
App.jsx
import React, { Component } from "react";
import Count from './components/Count'
export default class App extends Component {render() {return <div><Count/></div>;}
}
components/Count/index.jsx
import React, { Component } from 'react'export default class Count extends Component {state = {count:0}// 加法increment=()=>{const {value} = this.selectNumberconst {count} = this.statethis.setState({count:count+value*1 //强制类型转换,value是一个字符串})}// 减法decrement=()=>{const {value} = this.selectNumberconst {count} = this.statethis.setState({count: count-value*1})}//奇数在加incrementIfOdd=()=>{const {value} = this.selectNumberconst {count} = this.stateif(count %2 != 0){this.setState({count: count+value*1})}}//异步加incrementAsync=()=>{const {value} = this.selectNumberconst {count} = this.statesetTimeout(()=>{this.setState({count: count+value*1})}, 500)}render() {return (<div><h1>当前求和为:{this.state.count}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}
redux精简版
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./redux/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
// 将这个App重新调用一下render
// 由于DOM的diff算法在,所以不会引起页面的大部分重绘与重排
store.subscribe(() => {root.render(<App />);
});
App.jsx
import React, { Component } from "react";
import Count from './components/Count'
export default class App extends Component {render() {return <div><Count/></div>;}
}
redux/store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./count_reduce";
const store = createStore(countReducer);
// 暴露store
export default store;
redux/count_reduce.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log(preState, action, "99");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case "increment": //如果是加return preState + data;case "decrement": //如果是减return preState - data;default:return preState;}
}
components/Count/index.jsx
import React, { Component } from 'react'
// 引入store
import store from '../../redux/store'
export default class Count extends Component {state = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 如果页面很多的话,每个组件都这样写,redux状态更改之后,要render页面更新一下// componentDidMount(){// // 检测redux中状态的变化,只要变化,就调用render// store.subscribe(() =>{// // 直接调用不起作用// // this.render()// // 更新state里面的状态,但是什么都不写// // 只要调用了setState,紧接着就是调用render// this.setState({})// })// }// 加法increment=()=>{const {value} = this.selectNumberstore.dispatch({type: 'increment',data:value*1})}// 减法decrement=()=>{const {value} = this.selectNumberstore.dispatch({type: 'decrement',data:value*1})}//奇数在加incrementIfOdd=()=>{const {value} = this.selectNumberconst count = store.getState()if(count %2 !== 0){store.dispatch({type: 'increment',data:value*1})}}//异步加incrementAsync=()=>{const {value} = this.selectNumbersetTimeout(()=>{store.dispatch({type: 'increment',data:value*1})}, 500)}render() {return (<div><h1>当前求和为:{store.getState()}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}
redux完整版
其他文件代码相同:
redux
store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./count_reduce";
const store = createStore(countReducer);
// 暴露store
export default store;
count_reduce.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "./constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log(preState, action, "99");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
count_action.js
/*该文件专门为Count组件生成action对象
*/
// 这样写会被认为是函数体的对象
export const createIncrementAction = (data) => ({ type: "increment", data });export const createDecrementAction = (data) => ({ type: "decrement", data });
constant.js
/*该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错
*/
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
components/Count/index.jsx
import React, { Component } from 'react'
// 引入store,用于获取redux中保存状态
import store from '../../redux/store'
// 引入actionCreator,专门用于创建action对象
import {createIncrementAction,createDecrementAction} from '../../redux/count_action'
export default class Count extends Component {state = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 如果页面很多的话,每个组件都这样写,redux状态更改之后,要render页面更新一下// componentDidMount(){// // 检测redux中状态的变化,只要变化,就调用render// store.subscribe(() =>{// // 直接调用不起作用// // this.render()// // 更新state里面的状态,但是什么都不写// // 只要调用了setState,紧接着就是调用render// this.setState({})// })// }// 加法increment=()=>{const {value} = this.selectNumberstore.dispatch(createIncrementAction(value*1))}// 减法decrement=()=>{const {value} = this.selectNumberstore.dispatch(createDecrementAction(value*1))}//奇数在加incrementIfOdd=()=>{const {value} = this.selectNumberconst count = store.getState()if(count %2 !== 0){store.dispatch(createIncrementAction(value*1))}}//异步加incrementAsync=()=>{const {value} = this.selectNumbersetTimeout(()=>{store.dispatch(createIncrementAction(value*1))}, 500)}render() {return (<div><h1>当前求和为:{store.getState()}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}
redux异步action
redux文件
store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./count_reduce";
// const store = createStore(countReducer);
// 引入redux-thunk,用于支持异步action
import { thunk } from "redux-thunk";
// 暴露store
export default createStore(countReducer, applyMiddleware(thunk));
count-reduce.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "./constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log(preState, action, "99");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
count_action.js
/*该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "./constant.js";
// import store from "./store";
// 这样写会被认为是函数体的对象————见demo.html解释
// 同步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);};
};
components/Count/index.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 = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 如果页面很多的话,每个组件都这样写,redux状态更改之后,要render页面更新一下// componentDidMount(){// // 检测redux中状态的变化,只要变化,就调用render// store.subscribe(() =>{// // 直接调用不起作用// // this.render()// // 更新state里面的状态,但是什么都不写// // 只要调用了setState,紧接着就是调用render// this.setState({})// })// }// 加法increment=()=>{const {value} = this.selectNumberstore.dispatch(createIncrementAction(value*1))}// 减法decrement=()=>{const {value} = this.selectNumberstore.dispatch(createDecrementAction(value*1))}//奇数在加incrementIfOdd=()=>{const {value} = this.selectNumberconst 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} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}
react-redux的基本使用
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./redux/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
// 将这个App重新调用一下render
// 由于DOM的diff算法在,所以不会引起页面的大部分重绘与重排
// 监测redux中状态的改变,如果redux的状态改变了,那么重新渲染App组件
store.subscribe(() => {root.render(<App />);
});
App.jsx
import React, { Component } from "react";
import Count from './containers/Count'
import store from './redux/store'
export default class App extends Component {render() {return (<div>{/* 给容器组件传递store */}<Count store={store} /></div>);}
}
redux文件
store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./count_reduce";
// const store = createStore(countReducer);
// 引入redux-thunk,用于支持异步action
import { thunk } from "redux-thunk";
// 暴露store
export default createStore(countReducer, applyMiddleware(thunk));
count_reduce.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "./constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log(preState, action, "99");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
count_action.js
/*该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "./constant.js";
// import store from "./store";
// 这样写会被认为是函数体的对象————见demo.html解释
// 同步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);};
};
Container/index.jsx
// 引入Count组件的UI组件
import CountUI from '../../components/Count'
// 引入store
// import store from '../../redux/store'
// 引入action
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction
} from '../../redux/count_action'
// 引入connect用于连接UI组件与redux
import {connect} from 'react-redux'// mapStateToProps函数的返回值作为状态传递给了UI组件
/*1.mapStateToProps函数返回的是一个对象2.mapStateToProps函数返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value————状态3.mapStateToProps用于传递状态
*/
// 在调用mapStateToProps函数的时候,别人已经帮你调用完了store.getState(),而且把返回的状态传递给了mapStateToProps函数,只需要接收递给UI组件就行
function mapStateToProps(state){return {count: state}
} //这样写相当于<CountUI n={900} />
/*1.mapDispatchToProps函数返回的是一个对象2.mapDispatchToProps函数返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value————操作状态的方法(dispatch)3.mapDispatchToProps用于传递操作状态的方法(dispatch)
*/
function mapDispatchToProps(dispatch){return {// 通知redux执行加法jia:number=>dispatch(createIncrementAction(number)),jian:number=>dispatch(createDecrementAction(number)),jiaAsync:(number,time)=>dispatch(createIncrementAsyncAction(number,time)),}
}
// connect()的返回值是一个函数
// const CountContainer = connect()(CountUI)
// 使用connect()()创建并暴露一个Count的容器组件
// export default CountContainer
// 这个地方的父子关系不是靠标签形成的父子关系,没有这样写<CountUI a="1" />,也就传递不了参数,那么就将要传递的参数在第一个()里面传递
export default connect(mapStateToProps,mapDispatchToProps)(CountUI)
Components/Count/index.jsx
import React, { Component } from 'react'
// 在UI组件中看不到任何与redux相关的API
export default class Count extends Component {state = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 加法increment=()=>{const {value} = this.selectNumberthis.props.jia(value*1)}// 减法decrement=()=>{const {value} = this.selectNumberthis.props.jian(value*1)}//奇数在加incrementIfOdd=()=>{const {value} = this.selectNumberif(this.props.count %2 !== 0){this.props.jia(value*1)}}//异步加incrementAsync=()=>{const {value} = this.selectNumberthis.props.jiaAsync(value*1,500)}render() {// console.log('UI组件接收到的props是',this.props);return (<div><h1>当前求和为:{this.props.count}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}
react-redux优化
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./redux/store";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
// 优化2
// 谁需要store,就给那个组件传递
// 批量给每个容器组件都传递了store对象
root.render(<Provider store={store}><App /></Provider>
);
App.jsx
import React, { Component } from "react";
import Count from './containers/Count'export default class App extends Component {render() {return (<div>{/* 给容器组件传递store */}<Count /></div>);}
}
redux文件
store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./count_reduce";
// const store = createStore(countReducer);
// 引入redux-thunk,用于支持异步action
import { thunk } from "redux-thunk";
// 暴露store
export default createStore(countReducer, applyMiddleware(thunk));
count_reduce.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "./constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log(preState, action, "99");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
count_action.js
/*该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "./constant.js";
// import store from "./store";
// 这样写会被认为是函数体的对象————见demo.html解释
// 同步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);};
};
contsiners/Count/index.jsx
// 引入Count组件的UI组件
import React, { Component } from 'react'// 引入action
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction
} from '../../redux/count_action'
// 引入connect用于连接UI组件与redux
import {connect} from 'react-redux'// 定义UI组件
class Count extends Component {state = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 加法increment=()=>{const {value} = this.selectNumberthis.props.jia(value*1) //这个地方接收到的是一个函数}// 减法decrement=()=>{const {value} = this.selectNumberthis.props.jian(value*1)}//奇数在加incrementIfOdd=()=>{const {value} = this.selectNumberif(this.props.count %2 !== 0){this.props.jia(value*1)}}//异步加incrementAsync=()=>{const {value} = this.selectNumberthis.props.jiaAsync(value*1,500)}render() {// console.log('UI组件接收到的props是',this.props);return (<div><h1>当前求和为:{this.props.count}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}// 使用connect()()创建并暴露一个Count的容器组件
// 语法精简与API精简
export default connect(state => ({count: state}),// mapDispatchToProps的一般写法
// dispatch =>({
// // 通知redux执行加法
// jia:number=>dispatch(createIncrementAction(number)),
// jian:number=>dispatch(createDecrementAction(number)),
// jiaAsync:(number,time)=>dispatch(createIncrementAsyncAction(number,time)),
// })// 优化1// mapDispatchToProps的简写{jia: createIncrementAction, //只需要写到action,就会自动调用dispatchjian: createDecrementAction,jiaAsync: createIncrementAsyncAction}
)(Count)
react-redux数据共享版
App.jsx
import React, { Component } from "react";
import Count from './containers/Count'
import Person from './containers/Person'export default class App extends Component {render() {return (<div>{/* 给容器组件传递store */}<Count /><hr /><Person /></div>);}
}
redux文件
store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware, combineReducers } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./reducers/count";
// 引入为Count组件服务的reducer
import personReducer from "./reducers/person";
// const store = createStore(countReducer);
// 引入redux-thunk,用于支持异步action
import { thunk } from "redux-thunk";
//多个reducer工作的时候,redux要管理多个状态,最好的办法是用一个对象去存储所有的东西,如果用数组存储,不好区分这是哪一个reducer
// 汇总所有的reducer变为一个总的reducer
const allReducer = combineReducers({he: countReducer,rens: personReducer,
});
// 暴露store
export default createStore(allReducer, applyMiddleware(thunk));
constant.js
/*该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错
*/
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
export const ADD_PERSON = "ADD_PERSON";
reducers文件
count.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "../constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log("countReducer@#@#@#");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
perosn.js
import { ADD_PERSON } from "../constant";
// 初始化人的列表
const initState = [{ id: "001", name: "Tom", age: 18 }];
export default function personReducer(preState = initState, action) {console.log("personReducer@#@#@#");const { type, data } = action;switch (type) {case ADD_PERSON: //若是添加一个人return [data, ...preState];default:return preState;}
}
actions文件
count.js
/*该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "../constant.js";
// import store from "./store";
// 这样写会被认为是函数体的对象————见demo.html解释
// 同步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);};
};
person.js
import { ADD_PERSON } from "../constant";
// 创建增加一个人的action对象
export const createAddPersonAction = (personObj) => ({type: ADD_PERSON,data: personObj,
});
containers文件
Person/index.jsx
import React, { Component } from 'react'
import { nanoid } from 'nanoid'
import { connect } from 'react-redux'
import { createAddPersonAction } from '../../redux/actions/person'
class Person extends Component {addPerson = () => {const name = this.nameNode.valueconst age = this.ageNode.value// console.log(name,age);const personObj = { id: nanoid(), name, age }this.props.jiaYiRen(personObj)this.nameNode.value = ''this.ageNode.value = ''}render() {return (<div><h2>我是Person组件,上方组件求和为:{this.props.he}</h2><input ref={c => this.nameNode = c} type="text" placeholder="输入名字" /><input ref={c => this.ageNode = c} type="text" placeholder="输入年龄" /><button onClick={this.addPerson}>添加</button><ul>{this.props.yiduiren.map(p =><li key={p.id}>{p.name}———{p.age}</li>)}</ul></div>)}
}
// 默认导出只有一个
// 容器组件里面有所有redux的状态
export default connect(state => ({ yiduiren: state.rens, he: state.he }), //映射状态{jiaYiRen: createAddPersonAction //映射操作状态的方法}
)(Person)
Count/index.jsx
// 引入Count组件的UI组件
import React, { Component } from 'react'// 引入action
import {createIncrementAction,createDecrementAction,createIncrementAsyncAction
} from '../../redux/actions/count'
// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'// 定义UI组件
class Count extends Component {state = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 加法increment = () => {const { value } = this.selectNumberthis.props.jia(value * 1) //这个地方接收到的是一个函数}// 减法decrement = () => {const { value } = this.selectNumberthis.props.jian(value * 1)}//奇数在加incrementIfOdd = () => {const { value } = this.selectNumberif (this.props.count % 2 !== 0) {this.props.jia(value * 1)}}//异步加incrementAsync = () => {const { value } = this.selectNumberthis.props.jiaAsync(value * 1, 500)}render() {// console.log('UI组件接收到的props是',this.props);return (<div><h2>我是Count组件,下方组件总人数为:{this.props.renshu}</h2><h1>当前求和为:{this.props.count}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}// 使用connect()()创建并暴露一个Count的容器组件
// 语法精简与API精简
export default connect(// 现在redux管理的是一个对象,所以state是一个对象,需要取出里面的数值state => ({ count: state.he, renshu: state.rens.length }),// mapDispatchToProps的简写{jia: createIncrementAction, //只需要写到action,就会自动调用dispatchjian: createDecrementAction,jiaAsync: createIncrementAsyncAction}
)(Count)
react-redux_开发者工具的使用
redux文件
stoe.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware, combineReducers } from "redux";
// 引入为Count组件服务的reducer
import countReducer from "./reducers/count";
// 引入为Count组件服务的reducer
import personReducer from "./reducers/person";
// const store = createStore(countReducer);
// 引入redux-thunk,用于支持异步action
import { thunk } from "redux-thunk";
// 引入redux-devtools-extension
import { composeWithDevTools } from "redux-devtools-extension";
//多个reducer工作的时候,redux要管理多个状态,最好的办法是用一个对象去存储所有的东西,如果用数组存储,不好区分这是哪一个reducer
// 汇总所有的reducer变为一个总的reducer
const allReducer = combineReducers({he: countReducer,rens: personReducer,
});
// 暴露store
export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk))
);
reducers
count.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "../constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log("countReducer@#@#@#");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
person.js
import { ADD_PERSON } from "../constant";
// 初始化人的列表
const initState = [{ id: "001", name: "Tom", age: 18 }];
export default function personReducer(preState = initState, action) {console.log("personReducer@#@#@#");const { type, data } = action;switch (type) {case ADD_PERSON: //若是添加一个人// 错误的写法,// 这样写会破坏一个规则,你的reducer就不是一个纯函数了// preState.unshift(data); //这种写法影响的是原数组,改写了参数数据,此处不可以这样写,这样会导致preState被改写了,personReducer就不是纯函数了// 会影响redux不能识别状态的改变// console.log(preState);// return preState;return [data, ...preState]; //拿到之前的人,放到了一个新的数组,这个数组和preState不是同一个数组// redux底层会判断操作的preState与返回的preState是不是一个,判断的是地址值,是不是指向了同一个default:return preState;}
}
// 举例,即便是推进去了一个数据,但是他们的地址值都是一样的
// let arr = [1, 3, 5, 7, 9];
// arr.push(10);
// 第一次调用和第二次调用的返回值不一样
// function demo(a) {
// // a = 9 改写了参数就不纯函数了
// return Math.random() + a;
// }
actions
count.js
/*该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "../constant.js";
// import store from "./store";
// 这样写会被认为是函数体的对象————见demo.html解释
// 同步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);};
};
person.js
import { ADD_PERSON } from "../constant";
// 创建增加一个人的action对象
export const createAddPersonAction = (personObj) => ({type: ADD_PERSON,data: personObj,
});
最终版
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import store from "./redux/store";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
// 优化2
// 谁需要store,就给那个组件传递
// 批量给每个容器组件都传递了store对象
root.render(// 此处需要用Provider包裹App,目的是让App所有后代容器组件都能接收到store<Provider store={store}><App /></Provider>
);
App.jsx
import React, { Component } from "react";
import Count from './containers/Count' //引入Count的容器组件
import Person from './containers/Person' //引入Person的容器组件export default class App extends Component {render() {return (<div>{/* 给容器组件传递store */}<Count /><hr /><Person /></div>);}
}
redux文件
store.js
/*该文件用于暴露一个store对象,整个应用只有一个store对象
*/
//引入createStore,专门用于创建redux中最为核心的store对象
import { createStore, applyMiddleware, combineReducers } from "redux";
// 引入汇总之后的reducer
import reducer from "./reducers";
// const store = createStore(countReducer);
// 引入redux-thunk,用于支持异步action
import { thunk } from "redux-thunk";
// 引入redux-devtools-extension
import { composeWithDevTools } from "redux-devtools-extension";// 暴露store
export default createStore(reducer,composeWithDevTools(applyMiddleware(thunk))
);
constant.js
/*该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错
*/
export const INCREMENT = "increment";
export const DECREMENT = "decrement";
export const ADD_PERSON = "ADD_PERSON";
reducers文件
count.js
/*1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数2.reducer函数会接收到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
import { INCREMENT, DECREMENT } from "../constant.js";
const initState = 0; //初始化状态
export default function countReducer(preState = initState, action) {console.log("countReducer@#@#@#");if (preState === undefined) preState = 0;// 从action对象中获取:type、dataconst { type, data } = action;//根据type决定如何加工数据switch (type) {case INCREMENT: //如果是加return preState + data;case DECREMENT: //如果是减return preState - data;default:return preState;}
}
person.js
import { ADD_PERSON } from "../constant";
// 初始化人的列表
const initState = [{ id: "001", name: "Tom", age: 18 }];
export default function personReducer(preState = initState, action) {console.log("personReducer@#@#@#");const { type, data } = action;switch (type) {case ADD_PERSON: //若是添加一个人// 错误的写法,// 这样写会破坏一个规则,你的reducer就不是一个纯函数了// preState.unshift(data); //这种写法影响的是原数组,改写了参数数据,此处不可以这样写,这样会导致preState被改写了,personReducer就不是纯函数了// 会影响redux不能识别状态的改变// console.log(preState);// return preState;return [data, ...preState]; //拿到之前的人,放到了一个新的数组,这个数组和preState不是同一个数组// redux底层会判断操作的preState与返回的preState是不是一个,判断的是地址值,是不是指向了同一个default:return preState;}
}
// 举例,即便是推进去了一个数据,但是他们的地址值都是一样的
// let arr = [1, 3, 5, 7, 9];
// arr.push(10);
// 第一次调用和第二次调用的返回值不一样
// function demo(a) {
// // a = 9 改写了参数就不纯函数了
// return Math.random() + a;
// }
index.js
// 该文件用于汇总所有的reducer为一个总的reducer
// 引入combineReducers,用于汇总多个reducer
import { combineReducers } from "redux";// 引入为Count组件服务的reducer
import count from "./count";
// 引入为Person组件服务的reducer
import persons from "./person";//多个reducer工作的时候,redux要管理多个状态,最好的办法是用一个对象去存储所有的东西,如果用数组存储,不好区分这是哪一个reducer
// 汇总所有的reducer变为一个总的reducer
const allReducer = combineReducers({count,persons
});
export default allReducer;
actions
count.js
/*该文件专门为Count组件生成action对象
*/
import { INCREMENT, DECREMENT } from "../constant.js";
// import store from "./store";
// 这样写会被认为是函数体的对象————见demo.html解释
// 同步action,就是指action的值为Object类型的一般对象
export const increment = (data) => ({ type: INCREMENT, data });export const decrement = (data) => ({ type: DECREMENT, data });
// 所谓的异步action就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的
export const incrementAsync = (data, time) => {return (dispatch) => {setTimeout(() => {dispatch(increment(data));}, time);};
};
person.js
import { ADD_PERSON } from "../constant";
// 创建增加一个人的action对象
export const addPerson = (personObj) => ({type: ADD_PERSON,data: personObj,
});
containers文件
Person/index.jsx
import React, { Component } from 'react'
import { nanoid } from 'nanoid'
import { connect } from 'react-redux'
import { addPerson } from '../../redux/actions/person'
class Person extends Component {addPerson = () => {const name = this.nameNode.valueconst age = this.ageNode.value * 1// console.log(name,age);const personObj = { id: nanoid(), name, age }this.props.addPerson(personObj)this.nameNode.value = ''this.ageNode.value = ''}render() {return (<div><h2>我是Person组件,上方组件求和为:{this.props.count}</h2><input ref={c => this.nameNode = c} type="text" placeholder="输入名字" /><input ref={c => this.ageNode = c} type="text" placeholder="输入年龄" /><button onClick={this.addPerson}>添加</button><ul>{this.props.persons.map(p =><li key={p.id}>{p.name}———{p.age}</li>)}</ul></div>)}
}
// 默认导出只有一个
// 容器组件里面有所有redux的状态
export default connect(state => ({ persons: state.persons, count: state.count }), //映射状态{addPerson //映射操作状态的方法}
)(Person)
Count/index.jsx
// 引入Count组件的UI组件
import React, { Component } from 'react'// 引入action
import {increment,decrement,incrementAsync
} from '../../redux/actions/count'
// 引入connect用于连接UI组件与redux
import { connect } from 'react-redux'// 定义UI组件
class Count extends Component {state = {// count: 0, //将这个地方的count去掉carName: '奔驰c63'}// 加法increment = () => {const { value } = this.selectNumberthis.props.increment(value * 1) //这个地方接收到的是一个函数}// 减法decrement = () => {const { value } = this.selectNumberthis.props.decrement(value * 1)}//奇数在加incrementIfOdd = () => {const { value } = this.selectNumberif (this.props.count % 2 !== 0) {this.props.increment(value * 1)}}//异步加incrementAsync = () => {const { value } = this.selectNumberthis.props.incrementAsync(value * 1, 500)}render() {// console.log('UI组件接收到的props是',this.props);return (<div><h2>我是Count组件,下方组件总人数为:{this.props.personCount}</h2><h1>当前求和为:{this.props.count}</h1><select ref={c => this.selectNumber = c} name="" id=""><option value="1">1</option><option value="2">2</option><option value="3">3</option></select> <button onClick={this.increment}>+</button> <button onClick={this.decrement}>-</button> <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button> <button onClick={this.incrementAsync}>异步加</button></div>)}
}// 使用connect()()创建并暴露一个Count的容器组件
// 语法精简与API精简
export default connect(// 现在redux管理的是一个对象,所以state是一个对象,需要取出里面的数值state => ({ count: state.count, personCount: state.persons.length }),// mapDispatchToProps的简写{increment, //只需要写到action,就会自动调用dispatchdecrement,incrementAsync}
)(Count)
测试代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><script type="text/javascript">// const a = (b) => {// data: b;// }; //undefined// const a = (b) => {// return { data: b };// }; //{data: 9}const a = (b) => ({ data: b }); //{data: 9}console.log(a(9));</script></body>
</html>
笔记:
## 1.求和案例 redux 精简版(1).去除 Count 组件自身的状态(2).src 下建立:
-redux
-store.js
-count_reducer.js(3).store.js:
1).引入 redux 中的 createStore 函数,创建一个 store
2).createStore 调用时要传入一个为其服务的 reducer
3).记得暴露 store 对象(4).count_reducer.js:
1).reducer 的本质是一个函数,接收:prestate,action,返回加工后的状态
2).reducer 有两个作用:初始化状态,加工状态
3).reducer 被第一次调用时,是 store 自动触发的,传递的 prestate 是 undefined,action:@@REDUX/INIT(5).在 index.js 中监测 store 中状态的改变,一旦发生改变重新渲染<App/>
备注:redux 只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。## 2.求和案例 redux 完整版新增文件:
1.count_action.js 专门用于创建 action 对象
2.constant.js 放置容易写错的 type 值## 3.求和案例 redux 异步 action 版(1).明确:延迟的动作不想交给组件自身,想交给 action(2).何时需要异步 action:想要对状态进行操作,但是具体的数据靠异步任务返回。(3).具体编码:
1).yarn add redux-thunk,并配置在 store 中
2).创建 action 的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
3),异步任务有结果后,分发一个同步的 action 去真正操作数据。(4).备注:异步 action 不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步 action。## 4.求和案例 react-redux 基本使用(1).明确两个概念:
1).UI 组件:不能使用任何 redux 的 api,只负责页面的呈现、交互等。
2).容器组件:负责和 redux 通信,将结果交给 UI 组件。(2).如何创建一个容器组件————带 react-redux 的 connect 函数
connect(mapStateToProps,mapDispatchToProps)(UI 组件)
-mapStateToProps:映射状态,返回值是一个对象-mapDispatchToProps:映射操作状态的方法,返回值是一个对象(3).备注 1:容器组件中的 store 是靠 props 传进去的,而不是在容器组件中直接引入(4).备注 2:mapDispatchToProps,也可以是一个对象## 5.求和条例 react-redux 优化(1).容器组件和 UI 组件整合一个文件
(2).无需自己给容器组件传递 store,给<App/>包裹一个<Provider store={store}>即可。
(3).使用了 react-redux 后也不用再自己检测 redux 中状态的改变了,容器组件可以自动完成这个工作。
(4).mapDispatchToProps 也可以简单的写成一个对象
(5).一个组件要和 redux“打交道”要经过哪几步?
(1).定义好 UI 组件---不暴露
(2).引入 connect 生成一个容器组件,并暴露,写法如下:connect(
state =>({key:value}), //映射状态
{key:xxxxxAction} //映射操作状态的方法
)(UI 组件)
(4).在 UI 组件中通过 this.props.xxxxxxx 读取和操作状态## 6.求和案例 react-redux 数据共享版(1).定义一个 Person 组件,和 Count 组件通过 redux 共享数据。
(2).为 Person 组件编号:reducer、action,配置 constant 常量。
(3).重点:Person 的 reducer 和 Count 的 Reducer 要使用 combineReducers 进行分并,合并后的总状态是一个对象!!!
(4).交给 store 的是总 reducer,最后注意在组件中取出状态的时候,记得“取到位”。## 7.求和案例 react-redux 开发者工具的使用(1)、yarn add redux-devtools-extension
(2).store 中进行配置
import {composeWithDevTools} from "redux-devtools-extension"
const store = createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))## 8.求和案例 react-redux最终版
(1).所有变量名字要规范,尽量触发对象的简写形式。(2).reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer
相关文章:
react学习笔记4——React UI组件库与redux
流行的开源React UI组件库 material-ui(国外) 官网: http://www.material-ui.com/#/github: GitHub - mui/material-ui: Material UI: Comprehensive React component library that implements Googles Material Design. Free forever. ant-design(国内蚂蚁金服) 官网: Ant…...
Java学习手册:Spring 事务管理
一、事务管理的概念 事务是一组操作的集合,这些操作要么全部成功,要么全部失败。事务管理的目的是保证数据的一致性和完整性。在数据库操作中,事务管理尤为重要,例如银行转账、订单支付等场景都需要事务管理来确保数据的正确性。…...
SpringBoot研究生双选系统开发实现
概述 SpringBoot研究生双选信息发布系统,该系统实现了研究生与导师双向选择的全流程管理,采用主流SpringBoot框架开发,是学习企业级教育管理系统开发的优质资源。适合作为计算机专业设计项目或高校信息化建设参考,完整实现…...
springboot中异步接口实现所有方式_20250501
几种异步接口实现demo package org.dromara.controller.app;// 导入必要的依赖库import cn.dev33.satoken.annotation.SaIgnore; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import o…...
【Linux网络】I/O多路转接技术 - epoll
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
机器学习经典算法:用决策树原理优化新能源汽车续航能力
🔥 “用决策树重构新能源车能量大脑!算法推导代码实战全解,续航暴增15%” 决策树算法就像我们生活中做决策的 “流程指南”,通过层层判断得出最终结论。比如你去超市买水果,站在琳琅满目的货架前,就不自觉地…...
深入探讨宾馆一次性牙刷价格,市场价格区间差异大
在我们日常出行、住宿的时候,宾馆的一次性牙刷是常见的、标配的物品。许多人或许都会感到好奇,这些一次性牙刷到底值多少钱。下面就来深入探讨一下宾馆一次性牙刷价格方面的问题。 市场价格区间 宾馆一次性牙刷价格差距大,便宜的一支可能只…...
深入解析 .NET Kestrel:高性能 Web 服务器的架构与最佳实践
Kestrel 是 .NET 中用于处理 HTTP 请求的高性能 Web 服务器。作为 ASP.NET Core 的默认服务器,Kestrel 被设计为在高并发、高吞吐量的环境下表现优异,并且能够支持多种协议和跨平台操作。本文将深入探讨 Kestrel 的架构设计、工作原理、配置方式、性能优…...
ZYNQ 纯PL端逻辑资源程序固化流程
ZYNQ 纯PL端逻辑资源程序固化 ZYNQ的程序固化流程比传统的FPGA固化流程复杂很多,Vivado生成的bit文件无法直接固化在ZYNQ芯片中。因为ZYNQ 非易失性存储器的引脚(如 SD 卡、QSPI Flash)是 ZYNQ PS 部分的专用引脚。这些非易失性存储器由 PS …...
【树莓派Pico FreeRTOS】-FreeRTOS-SMP移植
FreeRTOS-SMP移植 文章目录 FreeRTOS-SMP移植1、Raspberry Pi Pico SDK准备2、下载最新FreeRTOS-Kernel源码3、Raspberry Pi Pico的开发环境搭建4、编译配置5、FreeRTOSConfig.h文件设置6、演示代码RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 …...
数字智慧方案5961丨智慧能源与运维云平台解决方案(52页PPT)(文末有下载方式)
详细资料请看本解读文章的最后内容。 资料解读:智慧能源与运维云平台解决方案 在当今数字化时代,能源管理与设备运维的智能化、高效化成为企业发展的关键。智慧能源与运维云平台解决方案应运而生,为企业提供了全面且先进的能源管理和运维手段…...
2025东三省C题深圳杯C题数学建模挑战赛数模思路代码文章教学: 分布式能源接入配电网的风险分析
完整内容请看文章最下面的推广群 数据整理与分析 表1:有源配电网62节点系统负荷参数 内容:列出了62个节点的有功负荷(单位:kW)。 特点: 负荷范围:24 kW(节点19)到420 …...
腾讯云BI VS quickbi 企业选型(从企业实际功能使用和费用对比)
腾讯云BI VS quickbi 选型 一、总结 前段时间领导让调研腾讯云BI,用来做BI选型,现根据公司实际使用功能做如下总结。 建议继续使用quickbi,不选择腾讯云BI 原因: 腾讯云BI专业版,官方价格最低101996元。并且只能选…...
WebDeveloper 流量分析、sudo提权,靶场通关WP
一、信息收集 1、主机探测 arp-scan -l netdiscover -i eth0 -r 192.168.33.0/24 nmap -sP 192.168.66.0/24 2、端口扫描 nmap -sS -sV 192.168.66.141 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0) 80/tcp op…...
编写教育网站后端页面笔记
callbacktitle.html 对应表: 对应的功能: 控制器层数据: 页面没有写内容 chapter.html 对应表: questionbank ,intofloortime,questionBank,title,didtitles,option,answer,analyse 对应的功能:问题反馈页面 控制器层数据(控制器类): ChapterQuestionbankTitle c…...
C++漫溯键值的长河:map set
文章目录 1.关联式容器2.set2.1 find2.2 lower_bound、upper_bound 3.multiset3.1 count3.2 equal_range 4.map4.1 insert4.2 operate->4.3 operate[ ]4.4 map的应用实践:随机链表的复制 5.multimap希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动…...
西门子数字化研发设计制造一体化规划案例P87(87页PPT)(文末有下载方式)
资料解读:《西门子数字化研发设计制造一体化规划案例》 详细资料请看本解读文章的最后内容。 该文档围绕西门子为企业打造的智能化制造研发工艺生产一体化平台规划方案展开,全面阐述了从业务现状分析到项目实施及案例分享的整个过程。 业务现状与需求分析…...
Rust多线程性能优化:打破Arc+锁的瓶颈,效率提升10倍
一、引言 在 Rust 开发中,多线程编程是提升程序性能的重要手段。Arc(原子引用计数)和锁的组合是实现多线程数据共享的常见方式。然而,很多程序员在使用 Arc 和锁时会遇到性能瓶颈,导致程序运行效率低下。本文将深入剖…...
基于python的人工智能应用简述
基于Python的人工智能应用简述 Python已成为人工智能(AI)开发的首选语言,凭借其简洁性、丰富的库生态系统和强大的社区支持,广泛应用于各类AI应用场景。以下是Python在人工智能领域的主要应用领域和技术实现。 1. 机器学习(Machine Learning) Python通过Scikit-learn、Ten…...
《Android 应用开发基础教程》——第十章:使用 Gson 实现网络 JSON 数据解析与对象映射
目录 第十章:使用 Gson 实现网络 JSON 数据解析与对象映射 🔹 10.1 什么是 Gson? 🔸 10.2 添加依赖 🔸 10.3 基础使用 ✦ 示例 JSON 字符串: ✦ 定义对应的 Java 类: ✦ JSON ➜ 对象&am…...
【Android】四大组件之BroadcastReceiver
目录 一、什么是BroadcastReceiver 二、创建和使用BroadcastReceiver 三、跨应用广播接收权限 四、广播方式 五、广播类型与特性 六、BroadcasReceiver注册方式 七、BroadcasReceiver工作流程 你可以把广播接收器想象成一个“收音机”。它的作用是监听系统或应用发出的“…...
[UVM]寄存器模型的镜像值和期望值定义是什么?他们会保持一致吗?
寄存器模型的镜像值和期望值定义是什么?他们会保持一致吗? 摘要:在 UVM (Universal Verification Methodology) 寄存器模型中,镜像值 (mirrored value) 和期望值 (desired value) 是两个非常重要的概念,用于管理寄存器…...
OpenGL-ES 学习(12) ---- VBO EBO VAO
目录 VBO 定义VBO 创建统一VertexData使用 VBO 绘制VAO VBO 定义 VBO(Vertex Buffer Object) 是指顶点缓冲区对象,而 EBO(Element Buffer Object)是指图元索引缓冲区对象,VBO 和 EBO实际上是同一类 buffer 按照用途的不同称呼 OpenGL-ES2.0 编程中&…...
【Redis分布式】主从复制
🔥个人主页: 中草药 🔥专栏:【中间件】企业级中间件剖析 一、主从复制 在分布式系统之中为了解决单点问题(1、可用性问题,该机器挂掉服务会停止2、性能支持的并发量是有限的)通常会把数据复制多…...
Node.js心得笔记
npm init 可用npm 来调试node项目 浏览器中的顶级对象时window <ref *1> Object [global] { global: [Circular *1], clearImmediate: [Function: clearImmediate], setImmediate: [Function: setImmediate] { [Symbol(nodejs.util.promisify.custom)]: [Getter] }, cl…...
多智能体空域协同中的伦理博弈与系统调停
在多智能体系统(MAS)广泛应用于低空飞行调度、应急响应与城市管理的背景下,AI之间的“协同”不仅是算法效率问题,更是伦理角色之间的权责动态博弈。尤其在高频互动、任务冲突、资源抢占等复杂场景中,智能体不再是“工具…...
面试中系统化地解答系统设计题:通用方法论
目录 一、明确需求(Clarify Requirements) (一)理解业务背景 (二)功能性需求(Functional Requirements) 1. 分析目标 2. 功能需求分类 A. 用户交互类功能 B. 数据处理类功能 C. 管理与运维类功能 D. 外部系统交互类功能 示例场景详解 3. 捕捉隐藏需求的技巧…...
kotlin中 热流 vs 冷流 的本质区别
🔥 冷流(Cold Flow) vs 热流(Hot Flow)区别 特性冷流(Cold Flow)热流(Hot Flow)数据生产时机每次 collect 才开始执行启动时就开始生产、始终运行生命周期与 collect 者…...
机器视觉开发-打开摄像头
以下是使用Python和OpenCV打开摄像头的最简单实现: import cv2# 打开默认摄像头(通常是0) cap cv2.VideoCapture(0)# 检查摄像头是否成功打开 if not cap.isOpened():print("无法打开摄像头")exit()print("摄像头已打开 - 按…...
Rerank详解
疑惑一 我对rag的流程理解是。后端首先建立embedding后的向量数据库,用户提问使用相同的embedding模型进行向量化,使用阈值控制相似度找出前topk个数据。然后rerank,将rerank的结果打包成prompt返回给大模型进行解答。我对于rerank的过程不是…...
深度探索DeepSeek:从架构设计到性能优化的实战指南
深度解码DeepSeek:从架构设计到工业级部署的全链路优化实践 引言:大模型时代的工程挑战 在人工智能技术进入工业化落地阶段的今天,大模型训练与推理的工程化能力已成为衡量企业技术实力的重要标尺。DeepSeek作为当前业界领先的超大规模语言…...
d202551
目录 一、175. 组合两个表 - 力扣(LeetCode) 二、511. 游戏玩法分析 I - 力扣(LeetCode) 三、1204. 最后一个能进入巴士的人 - 力扣(LeetCode) 一、175. 组合两个表 - 力扣(LeetCode…...
(C题|社交媒体平台用户分析问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合
我是Tina表姐,毕业于中国人民大学,对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在,我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…...
计网_PPP协议
2024.10.15:beokayy计算机网络学习笔记 PPP协议 PPP协议的特点PPP协议应满足的需求(了解)PPP协议的组成(PPP协议有三个组成部分) PPP协议的帧格式PPP协议的工作状态 ISP指的是运营商,比如中国联通、中国电信…...
Mem0.ai研究团队开发的全新记忆架构系统“Mem0”正式发布
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
二叉树删除结点详细代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h>typedef int data_t; typedef struct _node {data_t data;struct _node* left;struct _node* right; }node_t;int bst_create(node_t**, data_t);//函数声明BST创建 int bst…...
PyTorch线性代数操作详解:点积、矩阵乘法、范数与轴求和
本文通过代码示例详细讲解PyTorch中常用的线性代数操作,包括点积、矩阵乘法、范数计算以及按轴求和等操作,帮助读者掌握张量运算的核心方法。 1. 点积运算 点积(Dot Product)是两个向量对应元素相乘后求和的结果。 实现代码&…...
Java SE(6)——类和对象
1.初始面向对象 1.1 什么是面向对象 Java是一门纯面向对象的编程语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交换来完成一件事情 1.2 面向过程…...
Kubernetes(k8s)的API Server 组件原理与结合生产实战教程
一、API Server 架构深度解析 1. 核心架构设计 二、生产环境安全加固实战 1. 认证(Authentication) 2. 授权(Authorization) 3. 准入控制(Admission Control) 三、性能优化与调参 1. 关键启动参数 四…...
Java面试高频问题(31-33)
三十一、服务网格:东西向流量治理与故障注入 服务网格架构分层 mermaid graph BT subgraph Control Plane APilot --> BEnvoy Sidecar CMixer --> B DCitadel --> B end subgraph Data Plane B --> E服务A B --> F服务B B --> G服务C end 核心能…...
VSCode开发调试Python入门实践(Windows10)
我的Windows10上的python环境是免安装直接解压的Python3.8.x老版本,可参见《Windows下Python3.8环境快速安装部署。 1. 安装VSCode 在Windows 10系统上安装Visual Studio Code(VS Code)是一个简单的过程,以下是详细的安装方法与…...
C++——入门基础(2)
文章目录 一、前言二、C入门2.1 缺省参数2.2 函数重载2.2.1 参数类型不同2.2.1.1 整体参数类型不同2.2.1.2 参数类型顺序不同 2.2.2 参数个数不同2.2.3 避坑注意2.2.3.1无参与有参2.2.3.2 返回值不同 2.3 引用2.3.1 引用的概念2.3.2引用的结构2.3.3 引用的特点2.3.4引用的作用2…...
【MySQL】复合查询与内外连接
目录 一、复合查询 1、基本查询回顾: 2、多表查询: 3、自连接: 4、子查询: 单列子查询 多行子查询: 多列子查询: 在from语句中使用子查询: 5、合并查询: union࿱…...
第3篇:请求参数处理与数据校验
在 Web 开发中,请求参数处理与数据校验是保障系统稳定性的第一道防线。本文将深入探讨 Egg.js 框架中参数处理的完整解决方案,涵盖常规参数获取、高效校验方案、文件流处理等核心功能,并分享企业级项目中的最佳实践。 一、多场景参数获取策略…...
Android JIT编译:adb shell cmd package compile选项
Android JIT编译:adb shell cmd package compile选项 例如: adb shell cmd package compile -m speed -f --full 包名 配置参数指令说明: compile [-r COMPILATION_REASON] [-m COMPILER_FILTER] [-p PRIORITY] [-f] [--primary-dex] …...
排序算法——冒泡排序
一、介绍 「冒泡排序bubblesort」通过连续地比较与交换相邻元素实现排序。这个过程就像气泡从底部升到顶部一样,因此得名冒泡排序。 冒泡过程可以利用元素交换操作来模拟:从数组最左端开始向右遍历,依次比较相邻元素大小,如果“左…...
文献阅读篇#5:5月一区好文阅读,BFA-YOLO,用于建筑信息建模!(上)
期刊简介:《Advanced Engineering Informatics》创刊于2002年,由Elsevier Ltd出版商出版,出版周期Quarterly。该刊已被SCIE数据库收录,在中科院最新升级版分区表中,该刊分区信息为大类学科工程技术1区,2023…...
工行手机银行安全吗?在应用商店下载工商银行安全吗?
现在很多的人都会用手机银行,其中工行的使用几率也是比较高的,但大家在使用的过程中就会比较关心使用工行手机银行是否安全。如果直接在应用商店下载,是否有安全保障? 工行的手机银行会拥有较高的保障,从技术到服务都可…...
python如何word转pdf
在Python中,将Word文档(.docx或.doc)转换为PDF可以通过多种库实现。以下是几种常见的方法及详细步骤: 方法1:使用 python-docx comtypes(仅Windows,需安装Word) 适用于Windows系统…...
在阿里云 Ubuntu 24.04 上部署 RabbitMQ:一篇实战指南
前言 RabbitMQ 是业界常用的开源消息中间件,支持 AMQP 协议,易于部署、高可用、插件丰富。本文以阿里云 ECS 上运行的 Ubuntu 24.04 LTS 为例,手把手带你完成 RabbitMQ 从仓库配置到运行的全流程,并分享在国内环境下常见的坑与对应解决方案。 环境概况 操作系统:Ubuntu …...