[react]react-router-dom 与 redux 版本升级

[react]react-router-dom 与 redux 版本升级

  • 环境
  • 脚手架的升级
  • react-router-dom 升级
    • 关于路由相关文件的写法--react-router-dom 5.0.1
      • 入口渲染文件App.js
      • 路由框架src/views/root/index.js
      • 路由守卫 src/views/routerguide/index.jsx
      • 路由文件src/views/page.js
    • 关于路由相关文件的写法--react-router-dom 6.20.1方式1
      • 入口渲染文件App.js
      • 路由框架src/views/root/index.js
      • 报错信息
        • [RouterGuide] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
      • 路由守卫 src/views/routerguide/index.jsx
      • 路由文件src/views/page.js
    • 关于路由相关文件的写法--react-router-dom 6.20.1方式2
      • 入口渲染文件App.js
      • 路由框架src/views/root/index.js
      • 路由文件 src/views/page.js
    • 路由的跳转
      • 代码跳转
      • 标签跳转
  • 状态管理
    • React 状态管理--Redux4.0.4版本
      • action.js定义改变状态类型
      • connect.js定义组件需要修改的全局变量
      • redux.js 定义改变状态类型
      • store.js 定义所有的全局变量
      • App.js 全局变量的注册:
      • 组件使用全局变量
    • React 状态管理--Redux5.0.0版本
      • store.js 定义所有全局状态
      • store.js 定义所有全局状态--持久化版本
      • 组件使用全局变量:
      • 报错信息
        • store.js:60 A non-serializable value was detected in an action, in the path: `register`. Value: ƒ register2(key) { _pStore.dispatch({ type: REGISTER,key});}
  • 生命周期
  • 问题汇总
    • Module not found: Can't resolve 'web-vitals'
    • Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization
    • State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect()
    • Line 296:7: React Hook "useEffect" is called in function "next" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"

本文主要是数据状态管理的升级以及路由升级的相关设置

环境

  • node -v.18.15.0
  • react - 16.9.0

脚手架的升级

升级过程中遇到的各种各样的问题记录一下

官方提供了一部分[升级指南]–如何升级到 React 18,所以仅记录一些官网没有的问题

包之间是存在依赖性的,因此并不是同时升级所有的包是最优选择,首先选定必须要升级的包,先升级之后在运行查看

关于脚手架的升级可查看react脚手架的升级,我们最好是先升级脚手架

react-router-dom 升级

根据查看包的更新命令发现react-router-dom也已经由5.0.1升级到6.20.1版本了

发现之前的路由的写法已经不支持了

而官网上关于路由的介绍感觉有点混乱。。。

查了很多资料,最后整理一下

发现针对路由的配置简化了很多

关于路由相关文件的写法–react-router-dom 5.0.1

入口渲染文件App.js

Root 是所有路由的外框架,老版本是在./view/root/index中初始化所有的路由,新版本的可以直接配置在路由文件src/views/page.js中了

import React from 'react';
import Root from './view/root/index';
import {Router, Switch, Route} from "react-router-dom";
import {Provider} from 'react-redux';
import {store} from './reducer/store';
import {createBrowserHistory} from "history";const history = createBrowserHistory();class App extends React.Component {render(){return (<Provider store={store}><Router history={history}><Switch><Route component={Root}/></Switch></Router></Provider>);}
}
export default App;

路由框架src/views/root/index.js

//老版
import React from 'react';
import {Switch, Route, Redirect} from "react-router-dom";
import {routerMap} from "../../view/pages";
import RouterGuide from '../routerguide/index'
const pagesRoute = () => {return routerMap.map((item, index) => {if("/"==item.path){return <Route path="/" exact key={index} render={(props) => {return <Redirect to={{pathname: item.redirectPath, search: `${props.location.search}`}}/>}}/>}else{return <RouterGuide key={index} path={item.path} component={item.component} auth={item.auth}/>}      })
}class Root extends React.Component {render() {return (<div className="main-content"><Switch>{pagesRoute()}<Redirect to="/"/></Switch></div>)}
}
export default Root;

路由守卫 src/views/routerguide/index.jsx

import React from 'react';
import {Route} from "react-router-dom";
import {connect} from 'react-redux';
import {userMap} from '../../reducer/connect';
import {device} from 'device.js/dist/device'class RouterGuide extends React.Component {componentWillMount(){let {path, auth, userId} = this.propsif (window.WEIXIN && path !== "/mobile") {window.location.href = "/mobile";} else if (!device.mobile && path !== "/mobile") {window.location.href = "/mobile";} else if (device.mobile && !window.WEIXIN && ('' === userId.userId || null === userId.userId)) {if (auth) {window.location.href = "/index";}}}render(){let {path, component} = this.propsreturn (<Route path={path} component={component}/>)}
}export default connect(userMap.mapStateToProps, userMap.mapDispatchToProps)(RouterGuide);

路由文件src/views/page.js

//老版
import IndexPage from "../view/index/index";
import UserPage from "../view/user/index";
import DetailPage from "../view/detail/index";
import ResultPage from "../view/result/index";
export const routerMap=[{path:'/',redirectPath:'/index',errorPath:'/mobile',redirect:true,auth:false},{path:'/index',component:IndexPage,auth:false},{path:'/detail',component:DetailPage,auth:true},{path:'/user',component:UserPage,auth:true},{path:'/result',component:ResultPage,auth:false}
]

关于路由相关文件的写法–react-router-dom 6.20.1方式1

入口渲染文件App.js

import React from "react";
import { createBrowserRouter } from "react-router-dom"; 
import Root from './view/root/index';
function App() {return (<BrowserRouter><Root></Root></BrowserRouter>);
}
export default App;

路由框架src/views/root/index.js

import React,{Suspense} from "react";
import { Routes,Route,  Outlet } from "react-router-dom"; 
import {routerMap} from "../../view/pages";
import RouterGuide from '../routerguide/index'// React.LazyExoticComponent<ComponentType<any>>
const withGuard = (item) => {return (<RouterGuideelement={<Suspense><item.element /></Suspense>}auth={item.auth}/>);
};
const pagesRoute = () => {return routerMap.map((item, index) => {return (<Routepath={item.path}key={index}element={withGuard(item)}/>);});
};
function Root() {return (<div className="main-content"><Routes>{pagesRoute()}</Routes></div>);
}
export default Root;

报错信息

[RouterGuide] is not a component. All component children of must be a or <React.Fragment>

该问题是想要像5.0.1版本一样,在pagesRoute设置路由守卫的时候报错了,<Routes></Routes>的内部只能是<Route/>,哪怕是定义路由守卫都不可以

直接在element设置为函数也报错,会报错Functions are not valid as a React child,但是调用函数,并使用Suspense标签即可

路由守卫 src/views/routerguide/index.jsx

新版的路由守卫可以直接在定义路由文件的时候直接设置,也即在方式2中通过src/views/page.js文件中设置,也可以单独设置

import React, { useEffect, Suspense } from "react";
import { Route, useNavigate, useLocation, Navigate } from "react-router-dom";
import { store } from "../../reducer/store";
// 具体实现根据项目需求来进行处理,返回是路由地址。
const onRouterBefore = (one, auth) => {if (!device.mobile) {return "/mobile";} else if (auth) {const state = store.getState();return state.userId ? one.pathname : "/index";} else {return one.pathname;}
};
function RouterGuide({ element, auth }) {const location = useLocation();const navigate = useNavigate();const { pathname } = location;useEffect(() => {// onRouterBefore 是对路由地址进行处理的函数const nextPath = onRouterBefore(location, auth);if (nextPath && nextPath !== pathname) {//路由重定向navigate(nextPath, { replace: true });}}, [pathname]);return element;
}
export default RouterGuide;

路由文件src/views/page.js

路由守卫在定义时直接设置,并且相当于在配置文件中直接设定了Root是外框架,不像老版本是在Root编写的,写法更加方便简洁

import Root from "../view/root/index"
import IndexPage from "../view/index/index";
import UserPage from "../view/user/index";
import DetailPage from "../view/detail/index";
import ResultPage from "../view/result/index";const routerMap=[{path:'/',element:(IndexPage),errorElement: (ErrorPage),auth:false,},{path:'/index',element:(IndexPage),auth:false},{path:'/detail',element:(DetailPage),auth:true},{path:'/user',element:(UserPage),auth:true},{path:'/result',element:(ResultPage),auth:false}
]
export {routerMap}

关于路由相关文件的写法–react-router-dom 6.20.1方式2

入口渲染文件App.js

//App.js 升级版
import React from "react";
import { RouterProvider,createBrowserRouter } from "react-router-dom"; 
import { routerMap } from "./view/pages";const router = createBrowserRouter(routerMap);
function App() {return <RouterProvider router={router} />;
}
export default App;

路由框架src/views/root/index.js

import React from "react";
import { Route,  Outlet } from "react-router-dom"; 
function Root() {return (<div className="main-content"><Outlet /></div>);
}
export default Root;

路由文件 src/views/page.js

路由守卫在定义路由时直接设置,并且相当于在配置文件中直接设定了Root是外框架,不像老版本是手动引入Root,再在Root中引入路由拦截编写的,该方式写法更加方便简洁

import Root from "../view/root/index"
import IndexPage from "../view/index/index";
import UserPage from "../view/user/index";
import DetailPage from "../view/detail/index";
import ResultPage from "../view/result/index";// 具体实现根据项目需求来进行处理,返回是路由地址。
const onRouterBefore = (one, auth) => {if (!device.mobile) {return "/mobile";} else if (one.pathname == "/") {return "/index";} else if (auth) {const state = store.getState();return state.userId ? one.pathname : "/index";} else {return one.pathname;}
};
function Guard({ element, auth }) {const location = useLocation();const navigate = useNavigate();const { pathname } = location;useEffect(() => {// onRouterBefore 是对路由地址进行处理的函数const nextPath = onRouterBefore(location, auth);if (nextPath && nextPath !== pathname) {//路由重定向navigate(nextPath, { replace: true });}}, [pathname]);return element;
}
// React.LazyExoticComponent<ComponentType<any>>
const withGuard = (Comp, auth) => {return (<Guardelement={<Suspense><Comp /></Suspense>}auth={auth}/>);
};
const routerMap=[{path:'/',element:(Root),errorElement: (ErrorPage),auth:false,children:[{path:'/index',element:(IndexPage),auth:false},{path:'/detail',element:(DetailPage),auth:true},{path:'/user',element:(UserPage),auth:true},{path:'/result',element:(ResultPage),auth:false}]}
]
const pagesRoute = (list)=>{list.map(item=>{item.element=withGuard(item.element,item.auth)if(item.children){pagesRoute(item.children)}})
}
pagesRoute(routerMap)
export {routerMap}

路由的跳转

代码跳转

使用老版的history路由的化话,如上面代码介绍 使用 createBrowserHistory,实现跳转的方法:

let {history} = this.props;
history.push('/detail')

新版本跳转方法:

import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
navigate("/detail")

注意,不是 usenavigation,而是useNavigate跳转

标签跳转

   <Route path="/" element={<Navigate to="/index" replace />}/>

状态管理

React 状态管理–Redux4.0.4版本

  • “redux”: “^4.0.4”
  • “react-redux”: “^7.1.0”

action.js定义改变状态类型

const USERID = 'userId';
const USERNAME = 'userName';
const PHONE = 'phone';
const ADDRESS = 'address';
const action_userId = {type: USERID, text: 'update the user id'}
const action_userName = {type: USERNAME, text: 'update user name'}
const action_phone = {type: PHONE, text: 'update the phone'}
const action_address = {type: ADDRESS, text: 'update address'}
export {USERID,USERNAME,PHONE,ADDRESS,action_userId,action_userName,action_phone,action_address}

connect.js定义组件需要修改的全局变量

import {action_userId, action_userName,action_phone,action_address
} from './action.js'export const userMap = {mapStateToProps(state) {return state;},mapDispatchToProps(dispatch) {return {getUserId: () => {dispatch(action_userId)},getUserName: () => {dispatch(action_userName)}}}
};
//对使用到的状态更新
export const userInfoMap = {mapStateToProps(state) {return {userId: state.userId,phone: state.phone,address:state.address}},mapDispatchToProps(dispatch) {return {getUserId: () => {dispatch(action_userId)},getPhone: () => {dispatch(action_phone)},getAddress: () => {dispatch(action_address)}}}
};

redux.js 定义改变状态类型

import {combineReducers} from 'redux';
import {USERID,USERNAME,PHONE,ADDRESS} from './action.js'/*** 触发的处理函数* @param state  设置一个初始值,若没有显示该初始值* @param action  * @returns {({} & {userId: string})|{userId: string}}*/
const getUserId = (state = {userId: ''}, action) => {switch (action.type) {case USERID:return Object.assign({}, state, {userId: state.userId})default:return state}
}
/*** 身份证号* @param state* @param action* @returns {{userName: string}|({} & {userName: string})}*/
const getUserName = (state = {userName: ''}, action) => {switch (action.type) {case USERNAME:return Object.assign({}, state, {userName: state.userName})default:return state}
}
/**** @param state* @param action* @returns {({} & {phone: string} & {phone: *})|{phone: string}}*/
const getPhone = (state = {phone: ''}, action) => {switch (action.type) {case PHONELABEL:return Object.assign({}, state, {phoneLabel: state.phone})default:return state}
}/**** @param state* @param action* @returns {({} & {address: string} & {address: *})}*/
const getAddress = (state = {address: ''}, action) => {switch (action.type) {case ADDRESS:return Object.assign({}, state, {address: state.address})default:return state}
}
/*** 多个reducer方法 * @type {Reducer<any>}*/
export const allReducer = combineReducers({userId: getPersonId,userName: getUserName,address: getAddress,phone:getPhone,
})

store.js 定义所有的全局变量

import {createStore} from 'redux'
import {allReducer} from './redux'
export const store = createStore(allReducer)

App.js 全局变量的注册:

import React from 'react';
import {Router, Switch, Route} from "react-router-dom";
import {Provider} from 'react-redux';
import {store} from './reducer/store';import {createBrowserHistory} from "history";
import Template from './components/template/template';const history = createBrowserHistory();
class App extends React.Component {render(){return (<Provider store={store}><Router history={history}><Switch><Route component={Template}/></Switch></Router></Provider>);}
}
export default App;

组件使用全局变量

import React from 'react'
import {connect} from "react-redux";
import {userInfoMap} from "../../reducer/connect";
import {setTitle} from '../../global';
import axios from 'axios';
import './index.css'class index extends React.Component {constructor(props){super(props);this.next = this.next.bind(this);this.changeUserName = this.changeUserName.bind(this);this.changeAddress = this.changeAddress.bind(this);this.changePhone = this.changePhone.bind(this);this.clearValue = this.clearValue.bind(this);this.state = {userId:"",userName: '',phone: '',address: '',errorMes: ''}}clearValue(){this.setState({userName: '',phone: '',address: '',errorMes: ''})}changeUserName(event){let val = event.target.value;this.setState({userName: val,}, () => {if (val.length>10) {this.setState({errorMes: "最大输入10个字符"})}})}changeAddress(event){let val = event.target.value;this.setState({address: val,}, () => {if (val.length>10) {this.setState({errorMes: "最大输入10个字符"})}})}changePhone(event){let val = event.target.value;this.setState({phone: val,}, () => {if (val.length>11) {this.setState({errorMes: "最大输入11个字符"})}})}login(){let {userId, address, phone,userName} = this.props;axios({method:'post',url:"/login", data: {userName: this.state.userName,address: this.state.address,phone: this.state.phone}}).then((response) => {if (response.responseCode === "200") {//更新当前组件,局部状态变更this.setState({userId: response.data.userId}, () => {let {history} = this.props;history.push('/home')})//更新全局数据userId.userId = response.data.userId;address.address = response.data.address;phone.phone = response.data.phone;userName.userName = response.data.userName;} else {//局部状态变更this.setState({errorMes: '请求超时请稍后再试',}, () => {//状态变更后的回调函数// this.changeInput();})}})}next(){this.login();}//初次挂载完成componentDidMount(){setTitle("客户信息");}//组件卸载componentWillUnmount(){del();}render(){return (<div className="page"><div className="margin"><div className="form-group top10"><input type="text" value={this.state.userName}onChange={(e) => this.changeUserName(e)} placeholder="请输入您的姓名"/><i onClick={() => this.clearValue()}></i></div><div className="form-group top10"><input type="text" value={this.state.address}onChange={(e) => this.changeAddress(e)} placeholder="请输入您的地址"/><i onClick={() => this.clearValue()}></i></div><div className="form-group top10"><input type="text" value={this.state.phone}onChange={(e) => this.changePhone(e)} placeholder="请输入您的手机号"/><i onClick={() => this.clearValue()}></i></div><div className="form-group"><label onClick={() => this.next()}>下一步</label></div></div></div>)}
}export default connect(userInfoMap.mapStateToProps, userInfoMap.mapDispatchToProps)(index)

React 状态管理–Redux5.0.0版本

  • “redux”: “^5.0.0”
  • “@reduxjs/toolkit”: “^2.0.1”
  • “react”: “^18.2.0”

store.js 定义所有全局状态

import { createSlice, configureStore } from "@reduxjs/toolkit";const initialState = {userId: "",userName: "",phone: "",address: "",
};
const statusSlice = createSlice({name: "stateGlobal",initialState: initialState,reducers: {appReducer: (state, action) => {return Object.assign({}, state, {...action.payload});}}
});
export const store = configureStore({reducer: statusSlice.reducer
});
export const { appReducer } = statusSlice.actions;

store.js 定义所有全局状态–持久化版本

首先,需要添加持久化的包

npm i redux-persist

其次,修改相关代码

import { createSlice, configureStore } from "@reduxjs/toolkit";
import { persistStore, persistReducer, PERSIST} from "redux-persist";
import storage from "redux-persist/lib/storage";const initialState = {userId: "",userName: "",phone: "",address: "",
};
const statusSlice = createSlice({name: "stateGlobal",initialState: initialState,// devTools : 开启redux-devtools,默认开启,开发环境开启,生产环境关闭devTools: process.env.NODE_ENV === "development",reducers: {appReducer: (state, action) => {return Object.assign({}, state, {...action.payload});},otherReducer:(state, action) => {return Object.assign({}, state, {userId:action.payload});},}
});
//在localStorge中生成key为root的值
const persistConfig = {key: "root",version: 1,storage,blacklist: [] //设置某个reducer数据不持久化,
};
const reducers = persistReducer(persistConfig, statusSlice.reducer);
const store = configureStore({reducer: reducers,middleware: (getDefaultMiddleware) =>getDefaultMiddleware({serializableCheck: {//设置序列化检测ignoredActions: [PERSIST],//忽略的action类型ignoredActionPaths: [],//忽略action中的路径ignoredPaths: []//忽略state中的路径}// serializableCheck: false //关闭redux序列化检测})
});
const persistor = persistStore(store);
export const { appReducer } = statusSlice.actions;
export { store, persistor };

组件使用全局变量:

import React from 'react'
import { useNavigate } from "react-router-dom";
import { store, appReducer } from "../../reducer/store";
import {setTitle} from '../../global';
import axios from 'axios';
import './index.css'export default function Index() {const navigate = useNavigate();//获取全局数据const init=store.getState(); const [state,setState] = useState({userId:"",userName: '',phone: '',address: '',errorMes: ''})const clearValue=()=>{setState({...state,userName: '',phone: '',address: '',errorMes: ''})}const changeUserName=(event)=>{let val = event.target.value;setState({...state,userName: val,errorMes: val.length>10?"最大输入10个字符":state.errorMes})}const changeAddress=(event)=>{let val = event.target.value;setState({...state,address: val,errorMes: val.length>10?"最大输入10个字符":state.errorMes})}const changePhone=(event)=>{let val = event.target.value;setState({...state,phone: val,errorMes: val.length>11?"最大输入11个字符":state.errorMes})}const login=()=>{                 axios({method:'post',url:"/login", data: {userName: state.userName,address: state.address,phone: state.phone}}).then((response) => {if (response.responseCode === "200") {//更新当前组件,局部状态变更setState({...state,userId: response.data.userId})navigate('/home')//更新全局数据store.dispatch(appReducer({userId: response.data.userId,address: response.data.address,phone: response.data.phone,userName: response.data.userName,}))} else {//局部状态变更setState({...state,errorMes: "请求超时请稍后再试"})//状态变更后的回调函数,没法设置,setState不支持回调// changeInput();}})}const next=()=>{login();}//初次挂载完成useEffect(()=>{setTitle("客户信息");},[])//组件卸载useEffect(()=>{return ()=>{del();}})return (<div className="page"><div className="margin"><div className="form-group top10"><input type="text" value={state.userName}onChange={(e) => changeUserName(e)} placeholder="请输入您的姓名"/><i onClick={() => clearValue()}></i></div><div className="form-group top10"><input type="text" value={state.address}onChange={(e) => changeAddress(e)} placeholder="请输入您的地址"/><i onClick={() => clearValue()}></i></div><div className="form-group top10"><input type="text" value={state.phone}onChange={(e) => changePhone(e)} placeholder="请输入您的手机号"/><i onClick={() => clearValue()}></i></div><div className="form-group"><label onClick={() =>next()}>下一步</label></div></div></div>)
}

通过以上方式发现现有的状态管理比以前简单很多

报错信息

store.js:60 A non-serializable value was detected in an action, in the path: register. Value: ƒ register2(key) { _pStore.dispatch({ type: REGISTER,key});}
import { persistStore, persistReducer, PERSIST} from "redux-persist";
const store = configureStore({reducer: reducers,middleware: (getDefaultMiddleware) =>getDefaultMiddleware({serializableCheck: {// Ignore these action typesignoredActions: [PERSIST],// Ignore these field paths in all actionsignoredActionPaths: [],// Ignore these paths in the stateignoredPaths: []}// serializableCheck: false //关闭redux序列化检测})
});

一开始 middleware 写错了位置,写在了createSlice中,后来仔细检查代码发现是位置写错了!!!!

生命周期

老版本的生命周期非常清晰,新版版的因为不推荐组件式的组件,推荐的是函数式组件,然后生命周期就非常混乱

老版本比较关注:

  • 首次挂载
  • 卸载前
  • 状态更新的时候

发现 React18.2.0 采用的是函数式组件,并且状态更新的回调已经没有了,所以不能行云流水的在设置卸载前的功能了,挂载后需要执行的操作,并且因为每次状态更新都要重新渲染 DOM ,因此如果在之后的回调中需要设置操作,但是没有状态后的回调了,导致整体逻辑去设置的时候非常混乱,会存在很多坑!!!并且存在什么渲染两次!!!!!!!这些都需要自己考虑,感觉是对用户的维护成本很高
新版本的虽说是可以使用useEffect,但是逻辑非常不清晰,并且官网的手册也根本没有对这些变更给与非常明确的解决方案,感觉?#$%^&*,我们需要花大量的时间去考虑各个变量之间的关系,可以不可以在某个位置更新,反正目前为止在升级的过程中的维护感觉很痛苦,我在考略要不要放弃这个框架了。。。。。。

问题汇总

这里是升级过程中遇到的问题汇总

Module not found: Can’t resolve ‘web-vitals’

如果启动后发现以上报错信息,说明之前米有初始化该工具包,初始化一下即可

npm i web-vitals@2.1.4 -D

Cannot access ‘WEBPACK_DEFAULT_EXPORT’ before initialization

es6模块循环依赖问题导致,查找代码把循环依赖注释掉即可

State updates from the useState() and useReducer() Hooks don’t support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect()

在更新前,使用this.setState()修改状态,并且this.setState()是异步函数,有回调函数的;
包升级后,使用useState()修改状态,并且useState()是异步函数,但是没有回调函数

Line 296:7: React Hook “useEffect” is called in function “next” that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word “use”

这是本人在开发工程中,从网上查找相关资料,说是组件名称没有大写开头,可是本人组件名称是大写!!!!但是提示next不是React组件方法名 ,感觉有点莫名其妙,想到next确实小写,本人将 useEffect 方式写在了函数"next"中,移到组件根块下报错消失!!!!所以useEffect是必须直接使用在组件结构下

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

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

相关文章

Linuxwebserver项目

1.主函数mian signal(SIGPIPE,SIG_IGN); char pwd_path[256]"";记录工作目录 char * path getenv("PWD");获取当前目录工作路径 ///home/itheima/share/bjc34/07day/web-http strcpy(pwd_path,path);字符串复制函数 strcat(pwd_path…

《数据结构、算法与应用C++语言描述》- 平衡搜索树 -全网唯一完整详细实现插入和删除操作的模板类

平衡搜索树 完整可编译运行代码见&#xff1a;Github::Data-Structures-Algorithms-and-Applications/_34Balanced search tree 概述 本章会讲AVL、红-黑树、分裂树、B-树。 平衡搜索树的应用&#xff1f; AVL 和红-黑树和分裂树适合内部存储的应用。 B-树适合外部存储的…

[Ray Tracing: The Rest of Your Life] 笔记

前言 开年第一篇博客~ 整理了三四个小时才整理完orz。 这一部分是光线追踪三部曲的最后一部&#xff0c;主要介绍了蒙特卡洛积分、重要性采样等内容。场景上没有什么大的改变&#xff0c;基本上就是在Cornell Box中渲染的&#xff0c;本篇主要在加速收敛&#xff0c;提升渲染效…

LeetCode 2735. 收集巧克力【枚举】2043

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

【快速全面掌握 WAMPServer】09.如何在 WAMPServer 中安装 Composer

网管小贾 / sysadm.cc WAMPServer 的大名想必应该有不少人特别是新手小白们略有耳闻吧。 它是出自法国大神之手的一款 PHP 开发环境集成包&#xff0c;工作于 Windows 环境&#xff0c;类似于它这样的集成包在 Linux 平台上反正我是没找到&#xff0c;所以它应该算是对使用 Wi…

CollectionUtils

使用 CollectionUtils 类的常用方法 在Java开发中&#xff0c;我们经常需要对集合进行各种操作&#xff0c;而Apache Commons Collections库提供了一个方便的工具类 CollectionUtils&#xff0c;其中包含了许多实用的方法。在这篇博客中&#xff0c;我们将深入了解一些常用的方…

MIT线性代数笔记-第35讲-期末复习

目录 35.期末复习打赏 35.期末复习 已知一个矩阵 A A A满足 A x ⃗ [ 1 0 0 ] A \vec{x} \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} Ax ​100​ ​无解且 A x ⃗ [ 0 1 0 ] A \vec{x} \begin{bmatrix} 0 \\ 1 \\ 0 \end{bmatrix} Ax ​010​ ​仅有一个解 (1)求 A A A的…

call的一点奇怪的使用

Object.prototype.hasOwnProperty.call(initModal, method) 解释&#xff1a; 在这个特定的代码中&#xff0c;它用于检查 initModal 对象是否具有名为 method 的属性。 Object.prototype.hasOwnProperty 是一个内置的 JavaScript 方法&#xff0c;它可以检查一个对象是否具有…

linux安装rabbitmq

文章目录 前言一、下载安装包二、erlang1.安装依赖2.解压3.安装4.环境变量5.验证 三、rabbitmq1.安装依赖2.解压3.新建目录4.rabbitmq.env.conf5.rabbitmq.conf6.环境变量7.启动8.验证9.停止 四、安装web1.安装插件2.访问控制台界面 五、开机启动1.编写脚本2.设置开机启动3.测试…

硬件安全模块 (HSM)、硬件安全引擎 (HSE) 和安全硬件扩展 (SHE)的区别

术语 硬件安全模块 (HSM) &#xff1a;Hardware Security Modules硬件安全引擎 (HSE) &#xff1a;Hardware Security Engines安全硬件扩展 (SHE) &#xff1a; Secure Hardware Extensions 介绍 在汽车行业中&#xff0c;硬件安全模块 (HSM)、硬件安全引擎 (HSE) 和安全硬件…

Android长按图标展示快捷方式

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {new Thread(() -> {// 获取ShortcutManager实例ShortcutManager shortcutManager getSystemService(ShortcutManager.class);// 创建要添加的快捷方式ShortcutInfo.Builder shortcutBuilder new ShortcutInfo.Bui…

Java中如何实现负载均衡策略

1. 引言 当在Java应用程序中需要处理负载均衡时&#xff0c;通常涉及到多个服务器或服务实例&#xff0c;以确保请求能够分散到这些实例上&#xff0c;从而提高系统性能、可用性和可伸缩性。实现负载均衡策略可以通过多种方法&#xff0c;包括基于权重、轮询、随机选择、最少连…

[蓝桥杯2020国赛]答疑

答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序&#xff0c;同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下&#xff1a; 首先进入办公室&#xff0c;编号为 i 的同学需要 si​ 毫秒的时间。然后同学问…

大语言模型训练数据集

大语言模型的数据集有很多&#xff0c;以下是一些常用的&#xff1a; - 中文维基百科&#xff1a;这是一个包含大量中文文本的数据集&#xff0c;可用于训练中文语言模型。 - 英文维基百科&#xff1a;这是一个包含大量英文文本的数据集&#xff0c;可用于训练英文语言模型。 …

python脚本实现一次提取多个文件下的图片

problem formulation 有时候下载的数据集如下&#xff0c;就很烦&#xff0c;一个里面就一张图片 code import os import shutil# 定义源目录和目标目录 source_dir ./dataset/data/Detection destination_dir ./dataset/data/img# 确保目标目录存在&#xff0c;如果不存…

css原子化的框架Tailwindcss的使用教程(原始html和vue项目的安装与配置)

安装教程 中文官网教程 原始的HTML里面使用 新建文件夹npm init -y 初始化项目 安装相关依赖 npm install -D tailwindcss postcss-cli autoprefixer初始化两个文件 npx tailwindcss init -p根目录下新建src/style.css tailwind base; tailwind components; tailwind ut…

图神经网络--GNN从入门到精通

图神经网络--GNN从入门到精通 一、图的基本表示和特征工程1.1 什么是图1.2 图的基本表示1.3 图的性质--度&#xff08;degree)1.4 连通图&#xff0c;连通分量1.5有向图连通性1.6图直径1.7度中心性1.7特征中心性&#xff08; Eigenvector Centrality&#xff09;1.8中介中心性 …

CentOS 7 实战指南:目录操作命令详解

写在前面 想要在 CentOS 7 系统下更高效地进行目录操作吗&#xff1f;不要犹豫&#xff0c;在这里我为你准备了一篇精彩的技术文章&#xff01;这篇文章将带您深入了解 CentOS 7 下目录操作相关命令的使用方法。无论您是新手还是有一定经验的用户&#xff0c;这篇文章都将为您…

EasyNTS端口穿透服务新版本发布 0.8.7 增加隧道流量总数记录,可以知晓设备哪个端口耗费流量了

EasyNTS上云平台可通过远程访问内网应用&#xff0c;包含网络桥接、云端运维、视频直播等功能&#xff0c;极大地解决了现场无固定IP、端口不开放、系统权限不开放等问题。平台可提供一站式上云服务&#xff0c;提供直播上云、设备上云、业务上云、运维上云服务&#xff0c;承上…

金蝶云星空其他出库单,审核中/审批流中可以选择序列号设置

文章目录 其他出库单&#xff0c;审核中&#xff0c;审批流中可以选择序列号设置 其他出库单&#xff0c;审核中&#xff0c;审批流中可以选择序列号设置