React进阶之高阶组件HOC、react hooks、自定义hooks

React高级

  • 高阶组件 HOC
    • 属性代理
    • 反向继承
    • 属性代理和反向继承的区别
    • 实例
      • 实例一
      • 实例二
  • Hooks
    • Hooks API
      • useState:
      • useEffect:
      • useLayoutEffect:
      • useRef:
      • useContext:
      • useReducer:
      • useMemo
      • useCallback
    • 自定义Hooks

拓展:
ios、安卓、h5、小程序、app在移动端开发上有啥区别?
应用场景不同:

  1. 原生的native app开发,native需要客户端的发版才能做更新迭代
  2. 客户端嵌套页面webview 和 混合应用hybrid app开发 — 要做快的发版,更新迭代的话
  3. mini program - 小程序开发

高阶组件 HOC

hoc:higher order component
本身不是复杂的内容,也不是React官方提供,他是一种设计模式组成的高阶用法,接收一个组件作为参数并返回一个新的组件,React是用组件拼装页面的
简单来说,hoc是组件作为参数,返回值也是组件
HOC 主要用于代码复用,类似于Vue中的mixin

function HOC(WrappedComponent){return props=><WrappedComponent {...props} />
}

这里的props传递可以看作是 vue中的,this.$slots.defaults传递一样

//类的使用
function HOC(WrappedComponent){return class extends React.Component{constructor(props){super(props)}render(){const newProps={name:"zhangsan"}return <WrappedComponent {...props} {...newProps} />}}
}

class类的完整示例:

import React from 'react';// 创建 HOC,增强组件功能:withCounter 是我们定义的高阶组件,它接收一个组件(WrappedComponent)并返回一个新的组件。
function withCounter(WrappedComponent) {return class extends React.Component {constructor(props) {super(props);this.state = { count: 0 };}increment = () => {this.setState(prevState => ({ count: prevState.count + 1 }));};render() {return (<WrappedComponent{...this.props}count={this.state.count}        // 将新的 state(count)传递给原组件increment={this.increment}      // 将新的方法(increment)传递给原组件/>);}};
}// 创建一个基础组件,接收 count 和 increment 作为 props
function Counter({ count, increment }) {return (<div><p>Count: {count}</p><button onClick={increment}>Increment</button></div>);
}// 使用 HOC 包装 Counter 组件
const EnhancedCounter = withCounter(Counter);// 使用增强后的组件
export default function App() {return <EnhancedCounter />;
}

分类:

  1. 属性代理
  2. 反向继承

属性代理

返回的是原本的组件

  1. 代理props
function HOC(WrappedComponent){const newProps = {name:'zhangsan' }return props=><WrappedComponent {...props} {...newProps} />
}
  1. 模拟state
function HOC(WrappedComponent){return class extends React.Component {constructor(props){super(props)this.state = {name:"zhangsan"}this.onChange = this.onChange.bind(this)}onChange=(e)=>{this.setState({name:e.target.value})}render(){const newProps={name: {value: this.state.name,onChange:this.onChange}}return <WrappedComponent {...this.props} {...newProps} />}}
}function Demo(props) {const { name } = propsconst { value, onChange } = name;//props// 定义新的state方法
}// 在外部的组件中定义的state state:name,methods:onChange
// 传递给内部的 WrappedComponent,通过props的方式去传递给他,能够获取value和onChange事件,然后去消费它
  1. 条件渲染,基于返回组件做的自定义处理
function HOC(WrappedComponent) {// customif (show = false) {return <div>暂无数据</div>}return props=> <WrappedComponent {...props} />
}

反向继承

使用类组件的方式
返回的是新的组件

function HOC(WrappedComponent) {return class extends WrappedComponent{render() {return super.render();}}
}

这里,返回的新组件是原先的组件一比一复制过来的。

使用:

function HOC(WrappedComponent) {// componentDidMount 新加功能const didMount = WrappedComponent.prototype.componentDidMount;//原本组件的mount方法return class extends WrappedComponent{// constructor() { this.state=WrappedComponent.prototype.state}componentDidMount() {if (didMount) {//需要将这样的生命周期关联的事件绑定到自定义的类中didMount.bind(this)  //新的组件里面,将原本组件生命周期方法执行了一遍}// handle custom 自定义逻辑this.setState({number:2})}render() {return super.render();}}
}

举例使用:
计算组件渲染时间:

function withTiming(WrappedComponent) {return class extends WrappedComponent{constructor(props) {super(props);start = 0;end = 0;}componentWillMount() {  //继承链上的生命周期方法依次执行,由子到父的顺序执行,也就是说,先执行 withTiming 中的 componentWillMount,然后执行 WrappedComponent 中的 componentWillMountif (super.componentWillMount) {super.componentWillMount();}start+=Date.now()}componentDidMount() { //同理,先执行 withTiming 中的 componentDidMount,然后执行 WrappedComponent 中的 componentDidMountif (super.componentDidMount) {super.componentDidMount();}end += Date.now()console.error(`${WrappedComponent.name}渲染时间为${end - start}ms`) //也就是说,这里统计的渲染时间实际是继承链上所有组件生命周期渲染时间的总和}render() {return super.render();}}
}
export default withTiming(Home)

属性代理和反向继承的区别

属性代理本质上是在外部操作这个组件,由外到内;但是,反向继承是由内到外,返回一个新的组件。所以说,由内部操作的话,是可以操作组件的所有逻辑的,内部逻辑相对比较危险。

实例

实例一

// views/PageA.js
import React from 'react';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';class PageA extends React.Component {state = {movieList: [],}/* ... */async componentDidMount() {const movieList = await fetchMovieListByType('comedy');this.setState({movieList,});}render() {return <MovieList data={this.state.movieList} emptyTips="暂无喜剧"/>}
}
export default PageA;// views/PageB.js
import React from 'react';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';class PageB extends React.Component {state = {movieList: [],}// ...async componentDidMount() {const movieList = await fetchMovieListByType('action');this.setState({movieList,});}render() {return <MovieList data={this.state.movieList} emptyTips="暂无动作片"/>}
}
export default PageB;// 冗余代码过多
// HOC
import React from 'react';const withFetchingHOC = (WrappedComponent, fetchingMethod, defaultProps) => {return class extends React.Component {async componentDidMount() {const data = await fetchingMethod();this.setState({data,});}render() {return (<WrappedComponent data={this.state.data} {...defaultProps} {...this.props} />);}}
}// 使用:
// views/PageA.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';const defaultProps = {emptyTips: '暂无喜剧'}export default withFetchingHOC(MovieList, fetchMovieListByType('comedy'), defaultProps);// views/PageB.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';const defaultProps = {emptyTips: '暂无动作片'}export default withFetchingHOC(MovieList, fetchMovieListByType('action'), defaultProps);;// views/PageOthers.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';
const defaultProps = {...}
export default withFetchingHOC(MovieList, fetchMovieListByType('some-other-type'), defaultProps);

一般在工作中使用到的都是属性代理,很少用到反向继承,在统计性能指标的场景中可以用反向继承。
属性代理效果一般做公用逻辑的抽离
属性代理实例:
不用HOC:
views/PageA.js:

// views/PageA.js
import React from 'react';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';// PageA:喜剧片的渲染
class PageA extends React.Component {state = {movieList: [],}/* ... */async componentDidMount() {const movieList = await fetchMovieListByType('comedy');this.setState({movieList,});}render() {return <MovieList data={this.state.movieList} emptyTips="暂无喜剧"/>}
}
export default PageA;

views/PageB.js

// views/PageB.js
import React from 'react';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';// pageB:动作片的渲染
class PageB extends React.Component {state = {movieList: [],}// ...async componentDidMount() {const movieList = await fetchMovieListByType('action');this.setState({movieList,});}render() {return <MovieList data={this.state.movieList} emptyTips="暂无动作片"/>}
}
export default PageB;

=>冗余代码过多,使用HOC抽离:

// 冗余代码过多
// HOC
import React from 'react';//  包裹的组件        请求的方法     上述的emptyTips
const withFetchingHOC = (WrappedComponent, fetchingMethod, defaultProps) => {return class extends React.Component {async componentDidMount() {const data = await fetchingMethod();this.setState({data,});}render() {return (<WrappedComponent data={this.state.data} {...defaultProps} {...this.props} />);}}
}

views/PageA.js:

// 使用:
// views/PageA.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';const defaultProps = {emptyTips: '暂无喜剧'}export default withFetchingHOC(MovieList, fetchMovieListByType('comedy'), defaultProps);

views/PageB.js:

// views/PageB.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';const defaultProps = {emptyTips: '暂无动作片'}export default withFetchingHOC(MovieList, fetchMovieListByType('action'), defaultProps);

其他页面:

// views/PageOthers.js
import React from 'react';
import withFetchingHOC from '../hoc/withFetchingHOC';
import fetchMovieListByType from '../lib/utils';
import MovieList from '../components/MovieList';
const defaultProps = {...}
export default withFetchingHOC(MovieList, fetchMovieListByType('some-other-type'), defaultProps);

实例二

在vue中有自定义指令,像v-permission,通过自定义指令实现按钮的逻辑展示,但是在这里也能通过HOC来实现。
例如:

import React from 'react';
import { whiteListAuth } from '../lib/utils'; // 鉴权方法function AuthWrapper(WrappedComponent) {return class AuthWrappedComponent extends React.Component {constructor(props) {super(props);this.state = {permissionDenied: -1,};}async componentDidMount() {try {await whiteListAuth(); // 请求鉴权接口this.setState({permissionDenied: 0,});} catch (err) {this.setState({permissionDenied: 1,});}}render() {if (this.state.permissionDenied === -1) {return null; // 鉴权接口请求未完成}if (this.state.permissionDenied) {return <div>功能即将上线,敬请期待~</div>;}return <WrappedComponent {...this.props} />;}}
}export default AuthWrapper;

Hooks

上节内容回顾:

  1. 在props和state两个组件开发过程中,如果要定义组件内部中的变量,使用props还是state?
    state
  2. 在props过程中,props元素随着外部组件变化而变化,如何观察到props的一个变化呢?
    生命周期等,只要能够获取到新的props就可以
  3. props是外部传参的,外部传递参数可能是不同的,想要一个组件要改变它的props,用什么样的方式能够做到呢?
    dispatch,最直接的方式,将props转为state
  4. 将React组件封装的更好,根据这里的思路:官方中文链接,将共有的能力抽离出来,放到对应的state,props上即可。

类组件中不能使用hooks

Hooks API

Hooks官方

结合官网中看下面讲到的几个API就行

use:试验期,在React 19中才会用到,返回的是一个promise的结果,这个方法是用来读取promise的返回值的。能够获取到返回的结果,能够读取到context,不建议使用。

useState:

const [state, setState] = useState(initialState)
initialState:初始默认值,state:默认值的返回,setState就是修改state的方式

import { useState } from 'react';function MyComponent() {const [age, setAge] = useState(28);const [name, setName] = useState('Taylor');const [todos, setTodos] = useState(() => createTodos());  //初始值能够获取函数的返回结果,但是必须是同步的const [userInfo,setUserInfo]=useState({name:"Taylor",age:42})// userInfo.age=52  这种方法是不生效的//这样去修改对象种某个属性的值setUserInfo({...userInfo,age:52})...
}

useEffect:

添加随着状态的改变来触发它的动作,辅佐用,返回的结果用来清除它的辅佐用

import { useEffect } from 'react';
import { createConnection } from './chat.js';function ChatRoom({ roomId }) {const [serverUrl, setServerUrl] = useState('https://localhost:1234');useEffect(() => { //useEffect参数:1.接收一个函数 2.一个数组const connection = createConnection(serverUrl, roomId); //创建长连接connection.connect();return () => {  //返回这里用来销毁连接 connection.disconnect();};}, [serverUrl, roomId]); //当且仅当serverUrl或roomId发生变化时,会重新执行useEffect中的函数// ...
}

使用场景:
可以在请求数据中使用

import { useState, useEffect } from 'react';
import { fetchBio } from './api.js';export default function Page() {const [person, setPerson] = useState('Alice');const [bio, setBio] = useState(null);useEffect(() => {let ignore = false;setBio(null);fetchBio(person).then(result => {if (!ignore) {setBio(result);}});return () => {ignore = true;}}, [person]);return (<><select value={person} onChange={e => {setPerson(e.target.value);}}><option value="Alice">Alice</option><option value="Bob">Bob</option><option value="Taylor">Taylor</option></select><hr /><p><i>{bio ?? 'Loading...'}</i></p></>);
}

代码中的useEffect:

  useEffect(() => {let ignore = false;setBio(null);fetchBio(person).then(result => {if (!ignore) {setBio(result);}});return () => {ignore = true;}}, [person]);

如果第二个返回的数组中person没有值了,那么就是没有依赖项发生变化,就在初始化中执行一次,等同于 componentDidMount

useLayoutEffect:

是useEffect的一个版本,这两个传递的参数都一样,只不过触发setup函数的时间不一样
useEffect: 组件mount -> dom渲染 -> useEffect(()=>{},[deps])
useLayoutEffect:组件mount -> useLayoutEffect(()=>{},[deps]) -> dom渲染

const DemoUseLayoutEffect = () => {const target = useRef()useLayoutEffect(() => {/*我们需要在dom绘制之前,移动dom到制定位置*/const { x ,y } = getPositon() /* 获取要移动的 x,y坐标 */animate(target.current,{ x,y })}, []);return (<div ><span ref={ target } className="animate"></span></div>)
}

这里意味着先执行的useLayoutEffect的回调函数(执行动作animate),再去渲染的return返回中的div代码

需要在dom上渲染最终的结果就使用:useLayoutEffect
需要在dom上展示执行callback回调函数的动作,就使用useEffect

useRef:

与Vue3中的Ref类似,通过 ref.current 获取值,但是创建的 ref 并没有关联到元素上,ref 绑定的是真实的js对象
与 state区别:
const [a,setA]=useState(1) => 当执行setA时候,会执行 重新渲染 re-render
但是如果只想改变值,并不希望组件重新渲染,可以借助ref
const a=useRef(1)
a.current=2 => 不会触发视图的响应,也不会触发视图的更新

使用场景:

const inputRef = useRef(null);
.......
return <input ref={inputRef} />;
function handleClick() {inputRef.current.focus();
}

useContext:

/* 用useContext方式 */
const DemoContext = ()=> {const value = useContext(Context);/ my name is aaa /return <div> my name is { value.name }</div>
}/ 用Context.Consumer 方式 /
const DemoContext1 = ()=>{return <Context.Consumer>{/  my name is aaa  */}{ (value)=> <div> my name is { value.name }</div> }</Context.Consumer>
}export default ()=>{return <div><Context.Provider value={{ name:'aaa' }} ><DemoContext /><DemoContext1 /></Context.Provider></div>
}

创建的Context,是能通过Provider和Consumer两个地方去消费的
第一种是用useContext将我们的值关联起来,
第二种,通过Provider将value值关联起来了,就能在provider下层的所有节点上,这里是DemoContext,DemoContext1,
这两个节点,一方面通过 useContext获取到其中关联的value,另一种是通过Context.Consumer之间去获取。但是在平常开发过程中,一般是通过useContext和Provider去获取上层传递下来的状态

useReducer:

const DemoUseReducer = ()=>{/* number为更新后的state值,  dispatchNumbner 为当前的派发函数 */const [ number , dispatchNumbner ] = useReducer((state, action) => {const { payload , name  } = action/ return的值为新的state /switch(name) {case 'a':return state + 1case 'b':return state - 1 case 'c':return payload       }return state}, 0)return <div>当前值:{ number }{ / 派发更新 / }<button onClick={()=>dispatchNumbner({ name: 'a' })} >增加</button><button onClick={()=>dispatchNumbner({ name: 'b' })} >减少</button><button onClick={()=>dispatchNumbner({ name: 'c' , payload:666 })} >赋值</button>{ / 把dispatch 和 state 传递给子组件  */ }<MyChildren  dispatch={ dispatchNumbner } State={{ number }} /></div>
}

上述这两个useContext 和 useReducer 和Redux的逻辑是一样的

useMemo

是平常做响应式依赖的一个动作,类似于vue中的computed

// selectList 不更新时,不会重新渲染,减少不必要的循环渲染
const a=useMemo(() => (<div>{selectList.map((i, v) => (<spanclassName={style.listSpan}key={v} >{i.patentName} </span>))}</div>
), [selectList])

当selectList元素变化时候,重新执行回调函数,只不过,useMemo返回的结果,就是这个函数执行的结果,所以,在selectList不变的话,哪怕这个组件变化,这个a的结果也不会发生变化
适用于性能优化

// listshow, cacheSelectList 不更新时,不会重新渲染子组件
useMemo(() => (<Modalwidth={'70%'}visible={listshow}footer={[<Button key="back" >取消</Button>,<Buttonkey="submit"type="primary">确定</Button>]}> { /* 减少了PatentTable组件的渲染 */ }<PatentTablegetList={getList}selectList={selectList}cacheSelectList={cacheSelectList}setCacheSelectList={setCacheSelectList}/></Modal>), [listshow, cacheSelectList])
 // 减少组件更新导致函数重新声明const DemoUseMemo = () => {/ 用useMemo 包裹之后的log函数可以避免了每次组件更新再重新声明 ,可以限制上下文的执行 /const newLog = useMemo(() => {const log = () => {console.log(123)}return log}, [])return <div onClick={()=> newLog() } ></div>
}
// 如果没有加相关的更新条件,是获取不到更新之后的state的值的
const DemoUseMemo = () => {const [ number ,setNumber ] = useState(0)const newLog = useMemo(() => {const log = () => {/ 点击span之后 打印出来的number 不是实时更新的number值 /console.log(number)}return log/ [] 没有 number */  }, [])return <div><div onClick={() => newLog()} >打印</div><span onClick={ () => setNumber( number + 1 )  } >增加</span></div>
}

useCallback

useMemo返回的是函数执行的结果,useCallback返回的是这个函数

挂载时初始化,constructor 对应着 useLayoutEffect 初始化
componentDidMount 对应着 useLayoutEffect第二个参数不传
更新 对应着 useEffect 传递参数
shouldComponentUpdate 对应着 useMemo和useCallback
componentDidUpdate 对应着 useEffect 回调函数执行
componentWillUnmount 对应着 useEffect 返回函数的执行

也就是这样:

useLayoutEffect(() => {// componentDidMountreturn () => {// componentWillUnmount};
}, [])useEffect(() => {// componentDidUpdate
}, [deps])// shouldComponentUpdate
useMemo(); useCallback()

自定义Hooks

类似:

const [a,b,c,d]=useXXX(params1,parmas2)

这种形式的就叫做自定义hook
自定义hook中使用reactive中已有的hook

本质上是:用已有的hooks做相同某种功能的聚合,聚合后能够在其他某个地方取消费

const useTitle = (title) => { useEffect(() => { document.title = title; }, []);
}const App = () => {useTitle('Hello World');return <div>Hello World</div>;
}

保证代码是相对独立的

import { useState, useEffect } from 'react'const useScroll = (scrollRef) => {const [pos, setPos] = useState([0,0])useEffect(() => {function handleScroll(e){setPos([scrollRef.current.scrollLeft, scrollRef.current.scrollTop])}scrollRef.current.addEventListener('scroll', handleScroll)return () => {scrollRef.current.removeEventListener('scroll', handleScroll)}}, [])return pos
}export default useScroll// 用法
import React, { useRef } from 'react'
import { useScroll } from 'hooks'const Home = (props) => {const scrollRef = useRef(null)const [x, y] = useScroll(scrollRef)return <div><div ref={scrollRef}><div className="innerBox"></div></div><div>{ x }, { y }</div></div>
}

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

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

相关文章

FPGA实现任意角度视频旋转(二)视频90度/270度无裁剪旋转

本文主要介绍如何基于FPGA实现视频的90度/270度无裁剪旋转&#xff0c;旋转效果示意图如下&#xff1a; 为了实时对比旋转效果&#xff0c;采用分屏显示进行处理&#xff0c;左边代表旋转前的视频在屏幕中的位置&#xff0c;右边代表旋转后的视频在屏幕中的位置。 分屏显示的…

Blazor-选择循环语句

今天我们来说说Blazor选择语句和循环语句。 下面我们以一个简单的例子来讲解相关的语法&#xff0c;我已经创建好了一个Student类&#xff0c;以此类来进行语法的运用 因为我们需要交互性所以我们将类创建在*.client目录下 if 我们做一个学生信息的显示&#xff0c;Gender为…

数据结构——实验八·学生管理系统

嗨~~欢迎来到Tubishu的博客&#x1f338;如果你也是一名在校大学生&#xff0c;正在寻找各种编程资源&#xff0c;那么你就来对地方啦&#x1f31f; Tubishu是一名计算机本科生&#xff0c;会不定期整理和分享学习中的优质资源&#xff0c;希望能为你的编程之路添砖加瓦⭐&…

在 Ubuntu22.04 上安装 Splunk

ELK感觉太麻烦了&#xff0c;换个日志收集工具 Splunk 是一种 IT 工具&#xff0c;可帮助在任何设备上收集日志、分析、可视化、审计和创建报告。简单来说&#xff0c;它将“机器生成的数据转换为人类可读的数据”。它支持从虚拟机、网络设备、防火墙、基于 Unix 和基于 Windo…

【C++高并发服务器WebServer】-2:exec函数簇、进程控制

本文目录 一、exec函数簇介绍二、exec函数簇 一、exec函数簇介绍 exec 函数族的作用是根据指定的文件名找到可执行文件&#xff0c;并用它来取代调用进程的内容&#xff0c;换句话说&#xff0c;就是在调用进程内部执行一个可执行文件。 exec函数族的函数执行成功后不会返回&…

[ACTF2020 新生赛]Upload1

题目 以为是前端验证&#xff0c;试了一下PHP传不上去 可以创建一个1.phtml文件。对.phtml文件的解释: 是一个嵌入了PHP脚本的html页面。将以下代码写入该文件中 <script languagephp>eval($_POST[md]);</script><script languagephp>system(cat /flag);&l…

第24篇 基于ARM A9处理器用汇编语言实现中断<六>

Q&#xff1a;怎样设计ARM处理器汇编语言程序使用定时器中断实现实时时钟&#xff1f; A&#xff1a;此前我们曾使用轮询定时器I/O的方式实现实时时钟&#xff0c;而在本实验中将采用定时器中断的方式。新增第三个中断源A9 Private Timer&#xff0c;对该定时器进行配置&#…

SpringMVC新版本踩坑[已解决]

问题&#xff1a; 在使用最新版本springMVC做项目部署时&#xff0c;浏览器反复500&#xff0c;如下图&#xff1a; 异常描述&#xff1a; 类型异常报告 消息Request processing failed: java.lang.IllegalArgumentException: Name for argument of type [int] not specifie…

系统思考—复杂问题的根源分析

在企业中&#xff0c;许多问题看似简单&#xff0c;背后却潜藏着复杂的因果关系。传统的思维方式往往只能看到表面&#xff0c;而无法深入挖掘问题的真正根源。我们常常通过“表面解决”来应对眼前的症状&#xff0c;但这往往只是治标不治本。 比如&#xff0c;销量下降时&…

安装VMware17

一、VMware Workstation 简介 VMware Workstation是一款由VMware公司开发的功能强大的桌面虚拟化软件。它允许用户在单一的物理电脑上同时运行多个操作系统作为虚拟机&#xff08;VMs&#xff09;&#xff0c;每个虚拟机都可配置有自己的独立硬件资源&#xff0c;如CPU核心、内…

三、双链表

链表的种类有很多&#xff0c;单链表是不带头不循环单向链表&#xff0c;但双链表是带头循环双向链表&#xff0c;并且双链表还有一个哨兵位&#xff0c;哨兵位不是头节点 typedef int LTDataType;typedef struct ListNode{struct ListNode* next; //指针保存下⼀个结点的地址s…

【知识】可视化理解git中的cherry-pick、merge、rebase

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 这三个确实非常像&#xff0c;以至于对于初学者来说比较难理解。 总结对比 先给出对比&#xff1a; 特性git mergegit rebasegit cherry-pick功能合并…

SpringBoot开发(三)SpringBoot介绍、项目创建、运行

1. SpringBoot 1.1. SpringBoot介绍 Spring Boot给世界程序员带来了春天&#xff0c;越来越多的企业选择使用spring boot来开发他们的软件&#xff0c;因此学习spring boot是科技发展的必然趋势。本门课程将从web最基础的知识点开始讲起&#xff0c;逐步带你攻破spring boot的…

438. 找到字符串中所有字母异位词

【题目】&#xff1a;438. 找到字符串中所有字母异位词 class Solution { public:vector<int> findAnagrams(string s, string p) {vector<int> res;vector<int> curVec(26, 0); // 统计p中字母出现的次数for(char c : p) {curVec[c - a];}for(int l 0, r …

Leetcode-两数之和

1.暴力枚举 class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {int lennums.size();int i,j;for(i0;i<len;i){for(ji1;j<len;j){if(nums[i]nums[j]target){return{i,j};}}}return {i,j};} }; 新知识&#xff1a; return {…

边缘网关具备哪些功能?

边缘网关&#xff0c;又称边缘计算网关&#xff0c;部署在网络边缘&#xff0c;它位于物联网设备与云计算平台之间&#xff0c;充当着数据流动的“守门员”和“处理器”。通过其强大的数据处理能力和多样化的通信协议支持&#xff0c;边缘网关能够实时分析、过滤和存储来自终端…

高等数学学习笔记 ☞ 微分方程

1. 微分方程的基本概念 1. 微分方程的基本概念&#xff1a; &#xff08;1&#xff09;微分方程&#xff1a;含有未知函数及其导数或微分的方程。 举例说明微分方程&#xff1a;&#xff1b;。 &#xff08;2&#xff09;微分方程的阶&#xff1a;指微分方程中未知函数的导数…

【优选算法】9----长度最小的子数组

----------------------------------------begin-------------------------------------- 铁子们&#xff0c;前面的双指针算法篇就算告一段落啦~ 接下来是我们的滑动窗口篇&#xff0c;不过有一说一&#xff0c;算法题就跟数学题一样&#xff0c;只要掌握方法&#xff0c;多做…

计算机网络之链路层

本文章目录结构出自于《王道计算机考研 计算机网络_哔哩哔哩_bilibili》 02 数据链路层 在网上看到其他人做了详细的笔记&#xff0c;就不再多余写了&#xff0c;直接参考着学习吧。 1 详解数据链路层-数据链路层的功能【王道计算机网络笔记】_wx63088f6683f8f的技术博客_51C…

Kubernetes v1.28.0安装dashboard v2.6.1(k8s图形化操作界面)

准备工作 Kubernetes v1.28.0搭建教程请参考&#xff1a;Kubernetes v1.28.0集群快速搭建教程-CSDN博客 查看当前集群nodes都是ready状态 查看当前pods都是running状态 下载并修改配置文件 下载 recommended.yaml &#xff0c;下载好之后&#xff0c;进入文件编辑 下载地址…