React进阶之高阶组件HOC、react hooks、自定义hooks
React高级
- 高阶组件 HOC
- 属性代理
- 反向继承
- 属性代理和反向继承的区别
- 实例
- 实例一
- 实例二
- Hooks
- Hooks API
- useState:
- useEffect:
- useLayoutEffect:
- useRef:
- useContext:
- useReducer:
- useMemo
- useCallback
- 自定义Hooks
拓展:
ios、安卓、h5、小程序、app在移动端开发上有啥区别?
应用场景不同:
- 原生的native app开发,native需要客户端的发版才能做更新迭代
- 客户端嵌套页面webview 和 混合应用hybrid app开发 — 要做快的发版,更新迭代的话
- 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 />;
}
分类:
- 属性代理
- 反向继承
属性代理
返回的是原本的组件
- 代理props
function HOC(WrappedComponent){const newProps = {name:'zhangsan' }return props=><WrappedComponent {...props} {...newProps} />
}
- 模拟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事件,然后去消费它
- 条件渲染,基于返回组件做的自定义处理
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
上节内容回顾:
- 在props和state两个组件开发过程中,如果要定义组件内部中的变量,使用props还是state?
state - 在props过程中,props元素随着外部组件变化而变化,如何观察到props的一个变化呢?
生命周期等,只要能够获取到新的props就可以 - props是外部传参的,外部传递参数可能是不同的,想要一个组件要改变它的props,用什么样的方式能够做到呢?
dispatch,最直接的方式,将props转为state - 将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>
}
相关文章:
React进阶之高阶组件HOC、react hooks、自定义hooks
React高级 高阶组件 HOC属性代理反向继承属性代理和反向继承的区别实例实例一实例二 HooksHooks APIuseState:useEffect:useLayoutEffect:useRef:useContext:useReducer:useMemouseCallback 自定义Hooks 拓展ÿ…...
在亚马逊云科技上高效蒸馏低成本、高精度的Llama 3.1 405B模型(上篇)
在2024年的亚马逊云科技re:Invent全球云计算春晚里,亚马逊云科技CEO - Matt Garman介绍了亚马逊云科技的AI模型托管平台Amazon Bedrock上的模型蒸馏服务Model Distillation,令小李哥印象十分深刻。该功能可自动化地为特定场景的知识创建一个蒸馏模型。它…...
算法基础 -- 红黑树初识
红黑树初识 红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,它通过对每个节点增加颜色属性,以及在插入和删除节点时使用特定规则调整树结构来保持平衡。红黑树的特点是,在任何情况下,其树高都可以保持在…...
TTL 在 Redis 缓存中的作用
Redis TTL(Time To Live)与缓存的关系 TTL(Time To Live,生存时间)是 Redis 提供的一种自动过期机制,用于控制键值对的存活时间。当 TTL 到期后,Redis 会自动删除该键,避免长期占用…...
利用 SAM2 模型探测卫星图像中的农田边界
将 Segment Anything Model Version 2 应用于卫星图像以检测和导出农业地区田地边界的分步教程 🌟 简介 手动绘制田地边界是最耗时的任务之一,其准确性取决于绘制者的表现。然而,精确的边界检测在很多领域都有应用。例如,假设您…...
Java春招面试指南前言
在当今竞争激烈的就业市场中,对于即将踏入职场的Java开发者而言,春招是一次宝贵的机会。本博客专栏旨在为大家提供一份全面且实用的Java春招面试指南,助力大家顺利通过面试,开启职业生涯的新篇章。 无论你是初出茅庐的应届生&…...
安宝特方案 | 智能培训:安宝特AR如何提升企业技能培训的效率与互动性
随着企业不断推进数字化转型,传统培训方式已无法满足现代企业对高效、灵活培训的需求。尤其在技术更新频繁、工艺流程复杂、员工流动性大的环境中,传统培训模式的局限性愈加明显。为了提升培训质量、降低培训成本,并帮助员工迅速掌握新技能&a…...
Python网络自动化运维---用户交互模块
文章目录 目录 文章目录 前言 实验环境准备 一.input函数 代码分段解析 二.getpass模块 前言 在前面的SSH模块章节中,我们都是将提供SSH服务的设备的账户/密码直接写入到python代码中,这样很容易导致账户/密码泄露,而使用Python中的用户交…...
最新-CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机
CentOS 7 基于1 Panel面板安装 JumpServer 堡垒机 一、前言二、设备要求三、环境要求四、安装4.1 环境安装4.2 JumpServer安装4.3 访问JumpServerWeb端,进行登录 五、登录Web控制台 一、前言 JumpServer是广受欢迎的开源堡垒机。运维必备神器!JumpServe…...
【前端】Hexo 建站指南
文章目录 前言生成站点本地测试部署云端参考 前言 更好的阅读体验:https://blog.dwj601.cn/FrontEnd/Hexo/build-your-own-website-with-hexo/ 笔记记多了,想要分享给同学们一起交流进步,该怎么办?想要搭建一个属于自己的知识库…...
(Java版本)基于JAVA的网络通讯系统设计与实现-毕业设计
源码 论文 下载地址: cc基于JAVA的网络通讯系统设计与实现(源码系统论文)https://download.csdn.net/download/weixin_39682092/90299782https://download.csdn.net/download/weixin_39682092/90299782 第1章 绪论 1.1 课题选择的…...
WPF基础 | 初探 WPF:理解其核心架构与开发环境搭建
WPF基础 | 初探 WPF:理解其核心架构与开发环境搭建 一、前言二、WPF 核心架构2.1 核心组件2.2 布局系统2.3 数据绑定机制2.4 事件处理机制 三、WPF 开发环境搭建3.1 安装 Visual Studio3.2 创建第一个 WPF 应用程序 结束语优质源码分享 WPF基础 | 初探 WPFÿ…...
插入排序
直接插入排序 直接插⼊排序是⼀种简单的插⼊排序法,其基本思想是:把待排序的记录按其关键码值的⼤⼩逐个插 ⼊到⼀个已经排好序的有序序列中,直到所有的记录插⼊完为⽌,得到⼀个新的有序序列。 例如:我们玩扑克牌时&…...
2025最新 Docker 国内可用镜像源仓库地址(01月02日更新)
1. 添加docker镜像地址 使用编辑器打开配置文件 /etc/docker/daemon.json(如果没有该文件,可以新建一个) 2. vi daemon.json, 写入以下内容 {"builder": {"gc": {"defaultKeepStorage": "20GB",&…...
Java 反射与动态代理:实践中的应用与陷阱
Java 反射与动态代理:实践中的应用与陷阱 在现代Java应用中,反射和动态代理提供了强大的灵活性,但它们也带来了性能和复杂度上的挑战。本文将深入探讨这些技术在实际项目中的应用,分析它们可能导致的陷阱,并提供详细的…...
tp8读取mysql导出excel
环境:php8.3, thinkphp8.0, mysql8.0 use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\Style\Alignment; use think\facade\Db; use think\response\Json;class Index {public function index…...
【自己动手开发Webpack插件:开启前端构建工具的个性化定制之旅】
在前端开发的世界里,Webpack无疑是构建工具中的“明星”。它强大的功能可以帮助我们高效地打包和管理前端资源。然而,有时候默认的Webpack功能可能无法完全满足我们的特定需求,这时候就需要自定义Webpack插件来大展身手啦!今天&am…...
vue2使用flv.js在浏览器打开flv格式视频
组件地址:GitHub - bilibili/flv.js: HTML5 FLV Player flv.js 仅支持 H.264 和 AAC/MP3 编码的 FLV 文件。如果视频文件使用了其他编码格式就打不开。 flv.vue <template><div><el-dialog :visible.sync"innerVisibleFlv" :close-on-pre…...
Spring中的事务管理器TransactionManager
目录 一、主要功能 二、使用场景说明 在Spring框架中,事务管理器(TransactionManager)是用于管理事务的重要接口。它提供了对事务的全面控制,包括事务的状态管理和资源管理等功能。本文将详细介绍TransactionManager的主要功能、…...
MacOS安装Docker battery-historian
文章目录 需求安装battery-historian实测配置国内源相关文章 需求 分析Android电池耗电情况、唤醒、doze状态等都要用battery-historian, 在 MacOS 上安装 battery-historian,可以使用 Docker 进行安装runcare/battery-historian:latest。装完不需要做任…...
Charles 4.6.7 浏览器网络调试指南:HTTPS抓包(三)
概述 在现代互联网应用中,网络请求和响应是服务交互的核心。对于开发者和测试人员来说,能够准确捕获并分析这些请求,是保证系统稳定性和性能的关键。Charles作为一个强大的网络调试工具,不仅可以捕获普通的HTTP请求,还…...
c++解决常见内存泄漏问题——智能指针的使用及其原理
目录 前言: 1. 智能指针的使用及其原理 1. 1 智能指针的使用场景分析 1.2 RAII和智能指针的设计思路 1.3 C标准库智能指针的使用 1.3 1 auto_ptr 1.3 2 unique_ptr 1.3 3 shared_ptr(重) 1.3 4 weak_ptr 1.3 5 模拟实现删除器 2.智能指针的原…...
算法竞赛之离散化技巧 python
目录 离散化实战演练总结 离散化 不改变数据相对大小的情况下,对数据进行相应的下标映射,即离散化。 例如:【100,200,300,400,500】,离散化后为【1,2,3,4,5】 什么时候可以离散化:当数据只与它们之间的相对大小有关&a…...
1.CSS的三大特性
css有三个非常重要的三个特性:层叠性、继承性、优先级 1.1 层叠性 想通选择器给设置想听的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式。层叠性主要是解决样式冲突的问题。 <!DOCTYPE html> <html lang"en&…...
由于请求的竞态问题,前端仔喜提了一个bug
在平常的开发过程中,你可能会遇到这样一个bug。 测试:我在测一个输入框搜索的功能时,告诉你通过输入框输入的内容,和最终通过输入内容搜索出来的结果对不上。 前端:我是通过调用后端接口拿到的数据,这明显…...
HTML `<head>` 元素详解
在 HTML 文档中,<head> 元素是一个非常重要的部分,它包含了文档的元数据(metadata)和其他与文档相关的信息。虽然 <head> 中的内容不会直接显示在网页上,但它对网页的行为、样式和搜索引擎优化(…...
基于RAG构建Text2SQL的实战教程
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…...
GPT-4对话模型在客服中的应用与前景:开启智能客服新时代
GPT-4对话模型在客服中的应用与前景:开启智能客服新时代 随着人工智能技术的迅猛发展,基于深度学习的对话模型在各个领域中得到了广泛应用。其中,GPT-4对话模型在客服系统中的应用尤为引人注目。本文将探讨GPT-4在客服中的应用与未来发展前景,并结合具体代码示例进行说明。…...
我想通过python语言,学习数据结构和算法该如何入手?
学习数据结构和算法是编程中的重要基础,Python 是一个非常适合入门的语言。以下是学习数据结构和算法的步骤和建议: 1. 掌握 Python 基础 确保你对 Python 的基本语法、数据类型、控制结构(如循环、条件语句)、函数等有扎实的理…...
Java多线程的面试面试题及答案解析
什么是进程?什么是线程?有什么区别? 进程是系统资源分配的基本单位,拥有独立的地址空间。线程是 CPU 调度和分派的基本单位,是比进程更小的独立执行的单位,共享所在进程的内存空间等资源。一个进程可以包含…...
python flask中使用or查询和and查询,还有同时使用or、and的情况
在 Flask 中处理数据库查询时,通常会结合使用 ORM 工具,例如 SQLAlchemy。以下是 or 查询、and 查询以及两者同时使用的示例。 文章目录 基础准备1. 使用 or_ 查询2. 使用 and_ 查询3. 同时使用 or_ 和 and_4. 更加复杂的嵌套查询 基础准备 假设有一个…...
C# 解析视频流播放全解析
在多媒体技术日益发达的今天,视频流播放已经成为众多应用中不可或缺的功能。对于开发者而言,掌握如何使用编程语言来解析和播放视频流是一项重要的技能。本文将深入探讨如何使用 C# 来实现视频流的解析与播放。 一、视频流播放原理简介 视频流是将视频…...
关于为什么java中nextInt()和nextLine()不能混用 | nextInt()和nextInt()之类的可以一起用
键盘录入的区别: 第一套体系:遇到空格、制表符、回车都结束,并且都不接收 nextInt()、nextDouble()、next() 遇到空格、制表符、回车就结束,只接收其之前的数据,空格以及空格之后的数据都在缓冲区内,如果…...
计算机图形学:实验一 OpenGL基本绘制
1.OpenGL的环境配置: 集成开发环境Visual Studio Community 2019的安装: 在Windows一栏选择使用C的桌面开发;再转到“单个组件”界面,在“编译器、生成工具和运行时”一栏选择用于“Windows的C CMake工具”;然后转到…...
Node.js 到底是什么
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它允许开发者使用 JavaScript 编写服务器端代码。 一、主要特点 1. 事件驱动和非阻塞 I/O 模型 Node.js 采用事件驱动架构,通过回调函数处理 I/O 操作,这使得它在处理大量并发请…...
2022年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题5)
目录 任务描述 任务清单 (一)基础配置 (二)有线网络配置 (三)无线网络配置 (四)出口网络配置 附录1:拓扑图 附录2:地址规划表 任务描述 随着业务的发展,现在要对海琼银行进行全网改造,为其它区域的网络提供高效的保障服务。同时,海琼银行还针对各个分支行、网点的…...
智慧脚下生根,智能井盖监测终端引领城市安全新革命
在繁忙的都市生活中,我们往往只关注地面的繁华与喧嚣,却忽略了隐藏在地面之下的基础设施——井盖。这些看似不起眼的井盖,实则承担着排水、通讯、电力等重要功能,是城市安全运转的重要一环。然而,传统的井盖管理面临着…...
ES6 简单练习笔记--变量申明
一、ES5 变量定义 1.在全局作用域中 this 其实就是window对象 <script>console.log(window this) </script>输出结果: true 2.在全局作用域中用var定义一个变量其实就相当于在window上定义了一个属性 例如: var name "孙悟空" 其实就相当于执行了 win…...
MsfVenom木马制作及使用
msfvenom基本用法 1、功能介绍 msfvenom的功能:常用于生成木马,在目标机器执行,在本地机器kali中上线,与反弹shell类似。MsfVenom可以生成两种类型的攻击载荷: (1)Payload:Payloa…...
ChromeOS 132 版本更新
ChromeOS 132 版本更新 1. 企业定制化 Chrome Web Store 管理员现在可以使用新设置定制 Chrome Web Store 以适应他们管理的用户,包括以下功能: 添加公司标志添加首页横幅和自定义公告策划扩展集合实施基于类别的控制 这些设置可以通过管理员控制台进…...
MySQL(表空间)
开始前先打开此图配合食用 MySQL表空间| ProcessOn免费在线作图,在线流程图,在线思维导图 InnoDB 空间文件中的页面管理 后面也会持续更新,学到新东西会在其中补充。 建议按顺序食用,欢迎批评或者交流! 缺什么东西欢迎评论!我都…...
智能化加速标准和协议的更新并推动验证IP(VIP)在芯片设计中的更广泛应用
作者:Karthik Gopal, SmartDV Technologies亚洲区总经理 智权半导体科技(厦门)有限公司总经理 随着AI技术向边缘和端侧设备广泛渗透,芯片设计师不仅需要考虑在其设计中引入加速器,也在考虑采用速度更快和带宽更高的总…...
Chrome远程桌面无法连接怎么解决?
Chrome远程桌面连接已停止工作 Chrome远程桌面是一款极为便捷的浏览器插件,能够帮助用户将自己的计算机连接到其他设备,无论是手机、平板电脑还是其他电脑。然而,在实际使用中,许多用户可能会面临各种各样的问题,比如…...
springcloud alibaba 五大组件
Spring Cloud Alibaba是Spring Cloud的一个子项目,致力于为构建分布式应用提供一站式解决方案。它基于阿里巴巴的底层Java开源框架,主要包含以下五大核心组件: 1. Nacos(服务注册与配置中心) 功能:Nacos提…...
es 3期 第25节-运用Rollup减少数据存储
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
理解深度学习pytorch框架中的线性层
文章目录 1. 数学角度: y W x b \displaystyle y W\,x b yWxb示例 2. 编程实现角度: y x W T b \displaystyle y x\,W^T b yxWTb3. 常见错误与易混点解析4. 小结参考链接 在神经网络或机器学习的线性层(Linear Layer / Fully Connect…...
“上门按摩” 小程序开发项目:基于 SOP 的全流程管理
在竞争激烈的生活服务市场,“上门按摩” 服务需求日益增长。为满足这一需求,我们启动了 O2O 模式的 “上门按摩” 小程序开发项目,该项目涵盖客户端、系统管理端、技师端。以下将通过各类 SOP 对项目进行全面管理,确保项目顺利推进。 一、项目启动 SOP:5W2H 分析法 What(…...
【xcode 16.2】升级xcode后mac端flutter版的sentry报错
sentry_flutter 7.11.0 报错 3 errors in SentryCrashMonitor_CPPException with the errors No type named terminate_handler in namespace std (line 60) and No member named set_terminate in namespace std 替换sentry_flutter版本为: 8.3.0 从而保证oc的…...
Unity自学之旅05
Unity自学之旅05 Unity学习之旅⑤📝 AI基础与敌人行为🥊 AI导航理论知识(基础)开始实践 🎃 敌人游戏机制追踪玩家攻击玩家子弹碰撞完善游戏失败条件 🤗 总结归纳 Unity学习之旅⑤ 📝 AI基础与敌…...
LINUX下设置分离状态(Detached State)和未设置分离状态的主要区别在于线程资源的管理方式和线程的生命周期。以下是两种状态的对比:
1. 设置分离状态(Detached State) 资源管理: 线程终止时,系统会自动释放与线程相关的所有资源(如线程栈、线程控制块)。不需要其他线程显式回收(pthread_join)。 线程生命周期&…...