React系列(八)——React进阶知识点拓展

前言

在之前的学习中,我们已经知道了React组件的定义和使用,路由配置,组件通信等其他方法的React知识点,那么本篇文章将针对React的一些进阶知识点以及React16.8之后的一些新特性进行讲解。希望对各位有所帮助。


一、setState
(一)更新状态的2种写法

在之前更新state的时候,我们常常使用的是this.setState()方法进行状态的更新,传入的参数是一个{key:value}对象,用于对state中指定的值进行更新。比如下面更新count值的写法:

import React, { Component } from 'react'
export default class Demo extends Component {state = {count:0}increment = ()=>{const {count} = this.state;this.setState({count:count+1}}render() {return (<div>当前的数值为: {this.state.count}<br/><button onClick={this.increment}>点我+1</button></div>)}
}

上面的写法固然不错,但实际上setState函数传入的参数不仅可以是一个对象,还可以是一个函数,在函数中我们可以接收到入参state,然后直接进行状态的更新。我们之前之间传入一个对象,其实可以看成是这种函数写法的简写方式。

export default class Demo extends Component {state = {count:0}increment = ()=>{this.setState(state=>({count:state.count+1}));}render() {return (<div>当前的数值为: {this.state.count}<br/><button onClick={this.increment}>点我+1</button></div>)}
}

值得一提的是,虽然这种写法自带的state可以方便我们后续操作,但实际上我们还是用的比较少,毕竟直接传入对象相对来说更加简单~

(二)指定setState的回调函数

setState函数除了可以传入要更新的状态之外, 还可以接收第二个参数,更新完状态后的回调函数。我们可以先看下面这个案例:

export default class Demo extends Component {state = {count:0}increment = ()=>{this.setState(state=>({count:state.count+1}));console.log(this.state.count)}render() {return (<div>当前的数值为: {this.state.count}<br/><button onClick={this.increment}>点我+1</button></div>)}
}

按道理说,当点击按钮时,会对count的值进行+1操作,并打印出更新完状态的最新值,但实际的结果是:

setState演示用例

我们可以看到,此时打印的结果却是count未更新前的值,原因是setState()虽然是同步方法,但具体更新状态的方法却是异步的,如果想要更新最新状态值做某些操作的话,就需要我们把对应的操作放在回调函数中。

export default class Demo extends Component {state = {count:0}increment = ()=>{this.setState(state=>({count:state.count+1}),()=>{console.log(this.state.count)});}render() {return (<div>当前的数值为: {this.state.count}<br/><button onClick={this.increment}>点我+1</button></div>)}
}

使用回调函数之后,我们可以看到,打印的结果就是我们想要的了:


setState演示用例2
二、懒加载:lazyLoad

实际上当页面导航栏的对应着多个组件时,即使用户只需要使用其中的1个或者几个,但页面在加载的时候还是会将所有组件都加载出来,这其实是不太合理的。组件的懒加载就可以帮助我们解决这个问题。
同时,懒加载需要配合Suspense 一起使用。这样做的原因很简单:一次性把组件加载出来,虽然一开始全部加载的时候速度会比较慢,但后面打开的速度就会很快。而懒加载的话,由于还要再发一次网络请求,所以react会要求我们在等待结果返回的过程中,定义一个类似于Loading提示的组件,以此来提高用户体验(否则用户看到的将是白屏)

未使用懒加载之前,如上述所说,页面就可以把对应的组件都加载好了(我们可以直接在main.chunk.js文件中找到对应组件的代码):

懒加载演示用例1

而实际上,React本身就提供了lazy函数供我们对组件进行懒加载配置:

步骤1: 引入 lazy函数和Susqense组件
import React, { Component,lazy,Suspense} from 'react'
步骤2:使用lazy函数,把需要懒加载的组件作为参数传入
const About = lazy(()=>import('./About'))
const Home = lazy(()=>import('./Home'))
步骤三:使用Suspense组件,对路由进行包裹
 <Suspense><Route path="/about" component={About} /><Route path="/home" component={Home} />
</Suspense>
步骤四:定义Loading组件

在开头我们就解释过,使用懒加载的话只有当每次用户点击后,才会真正发起获取组件的网路请求,Loading组件存在的意义就是在请求的响应回来之前,页面上先显示Loading组件,不让页面出现白屏的效果。

import React, { Component } from 'react'export default class Loading extends Component {render() {return (<div><h1 style={{backgroundColor: "gray",color:'orange'}}>Loading...</h1></div>)}
}
步骤五:引入组件并将Loading组件作为回调传入Suspense组件中:
 <Suspense fallback={<Loading/>}><Route path="/about" component={About} /><Route path="/home" component={Home} />
</Suspense>
最终,我们可以在浏览器的控制台上查看效果:

lazyLoading演示用例2

当使用懒加载之后,只有当我们点击的时候,才会发起新的请求,这里的 0.chunk.js就是请求回来的结果,如果我们点进去看的话,就可以在其中发现我们的组件代码了。

三、Fragment标签的使用

我们知道,使用JSX语法定义组件时,会要求我们返回唯一一个根标签,但是这样有一个缺点:让我们的页面嵌套层次过深,我们可以使用 Fragment 或者 <></> 这种空标签来避免上述问题。需要注意的是,虽然二者都可以解决根标签的问题,但是在使用上二者还是有些不同的,Fragment标签中可以传递参数key,而空标签是不允许传递参数的。
我们可以看看未使用Fragment标签时,页面上的元素:

App组件
export default class App extends Component {render() {return (<div><Demo/></div>)}
}
Demo组件
export default class Demo extends Component {render() {return (<div><input /><br /><input /></div>)}
}
Fragment演示用例1

我们可以看到,虽然页面上的元素正常显示,但还是会嵌套在不需要使用到的div标签中,我们可以使用Fragment标签或者空标签来解决这个问题:

App组件:
import React, { Component,Fragment } from 'react'
import Demo from './4_fragement'export default class App extends Component {render() {return (<Fragment><Demo/></Fragment>)}
}
Demo组件
import React, { Component, Fragment } from 'react'export default class Demo extends Component {render() {return (<><input /><br /><input /></>)}
}
Fragment演示用例2

我们可以看到,使用<Fragment>或者使用<></>标签都有着使组件不需要有一个真实DOM标签的功能,但实际上二者在使用上还是略有不同的,Fragment标签可以接收key属性的参数,而空标签是不可以接收属性参数的。

四、实例对象Context属性的应用

我们知道,使用props属性自然可以将方法或者数据从父组件上逐层传递到子组件中。但是当组件间的嵌套关系比较深的时候,这时再通过props来传递值就会很麻烦,针对这种情况,我们可以考虑用Context来解决这个问题:Context其实是组件实例对象上的一个属性,利用ProviderConsumer,我们可以实现值的传递。
假如目前有A、B、C三个组件,B是A的子组件,C是B的子组件:

export default class A extends Component {state = { name: '小明', age: 18 }render() {const {name,age} = this.state;return (<div className="parent">我是A组件<br /><h4>姓名是:{this.state.name},年龄是:{this.state.age}</h4><B /></div>)}
}
class B extends Component {render() {return (<div className="child">我是B组件<C /></div>)}
}
class C extends Component {render() {return (<div className="grand">我是C组件<h4>从A组件获取到的值为</h4></div>)}
}

如果C组件想要获取A组件的值,我们可以通过以下步骤来实现:

步骤1:通过React.createContext(),获取ProviderConsumer
const MyContext = React.createContext();
const { Provider, Consumer } = MyContext;
步骤2:在A组件中使用Provider包裹住子组件
export default class A extends Component {state = { name: '小明', age: 18 }render() {const {name,age} = this.state;return (<div className="parent">我是A组件<br /><h4>姓名是:{this.state.name},年龄是:{this.state.age}</h4>{/* 使用Provider包裹住子组件,有需要的后代组件通过Consumer标签即可获取,需要注意,value传入的值是一个对象 */}<Provider value={{name,age}}><B /></Provider></div>)}
}
步骤3:在C组件中通过Consumer标签获取A组件的值
class C extends Component {render() {return (<div className="grand">我是C组件<h4>从A组件获取到的值为<Consumer>{value => `姓名为:${value.name},年龄为:${value.age}`}</Consumer></h4></div>)}
}
五、PureComponent的使用

对于子组件来说,一旦父组件重新render,那么其也会跟着一起重新执行一次render方法,即使子组件并没有使用到父组件传递的任何属性。或者当父组件空调用一次setState方法,那么此时state并没有真的改变,但是子组件还是要重新执行一次render,这其实是不太合理的。

export default class Parent extends Component {state = {carName:'哈雷摩托',stus:['小明','小红']}changeCar = ()=>{//this.setState({carName:'特斯拉'})this.setState({})}addStus = ()=>{this.setState({stus:['小明',...this.state.stus]})}render() {console.log('父组件的render方法调用了')const {carName,stus} = this.state;return (<div className="parent"><h3>父组件的车名为:{carName}</h3><h4>{stus}<button onClick={this.addStus}>点我加人</button></h4><button style={{marginBottom: '5px'}} onClick={this.changeCar}>点击换车</button><Child carName={carName}></Child></div>)}
}
class Child extends Component {render() {console.log('子组件的render方法调用了')return (<div className="child"><h4>接收到父组件的车名为:{this.props.carName}</h4></div>)}
}
pureComponent演示用例1

解决这个问题的方法有2个:

(1)手动写 componentShouldUpdate方法,对状态是否改变进行判断

比如我们可以通过下面这个钩子来避免组件发生无效的render:

    shouldComponentUpdate(nextProps,nextState){return nextState.carName !== this.state.carName }
(2)利用PureComponent组件,里面帮我们重写了shouldComponentUpdate方法

我们可以利用组件内componentShouldUpdate这个钩子,来根据实际需要判断是否执行render,但如果说状态比较多,就需要我们手动写很多判断条件,比较麻烦。我们更加常用的是直接继承和使用PureComponent组件。

import React, { Component,PureComponent } from 'react'
import './index.css'export default class Parent extends PureComponent {
...
}class Child extends PureComponent {...
}
pureComponent案例演示2
六、render props属性的应用

对于关系明确的父子组件来说,我们可以比较简单的从组件的嵌套关系来判断组件间的父子关系。但是有时候我们可能并不能确定父组件中的子组件具体是哪一个,而是等到具体调用的时候才知道。
比如说有A、B、C三个组件,且我们知道A是B的父组件,B是C的父组件,那么对应的代码为:

export default class A extends Component {render() {return (<div className="parent"><B/></div>)}
}class B extends Component {render() {return (<div className="parent"><C/></div>)}
}class C extends Component {render() {return (<div className="parent"></div>)}
}

但有时候我们可能只知道B组件内需要传递一个组件,但具体是哪个组件却不能确定,只能等到具体使用的时候才能确定,这个时候就需要用props的方法来解决了。
Vue中,这种问题的解决方案被称为插槽技术
React中,我们通常使用children props以及render props属性来解决这类问题。其中,children props虽然可以完成组件的传递,但是却不能实现父子组件的数据传递而render props则可以解决这类问题

export default class A extends Component {render() {return (<div className="parent"><B><C/></B></div>)}
}class B extends Component {render() {return (<div className="parent">{this.props.children}</div>)}
}class C extends Component {render() {return (<div className="parent"></div>)}
}

用上面这种方式,我们可以通过 通过组件标签体的方式传入组件,在对应的组件内使用{this.props.children}进行展示。这样就使得组件的灵活性大大提高,但这种方式的缺点也很明显,C组件虽然是B组件的子组件,但是却不能获取B组件的值。这时,就需要用到第二种方式:使用render props进行参数的传递。

export default class A extends Component {render() {return (<div className="parent"><B render={name => <C name={name} />}/></div>)}
}class B extends Component {state = {name:'小明'}render() {return (<div className="parent">{this.props.render(name)}</div>)}
}class C extends Component {render() {return (<div className="parent"><h4>接收到的父组件参数是: {this.props.name}</h4></div>)}
}

通过上述这种方式,我们就可以把父组件的参数传递给子组件了,需要注意的是本质上这里使用的还是组件的props属性,所以props不一定名字要叫render,只是很多时候我们约定俗成地将这种传递值的方式的props值设为render

七、错误边界:ErrorBoundary

当子组件发生错误时,我们会希望子组件的错误不影响到父组件其他功能的使用,这时候我们就可以在父组件上设置错误边界,来防止由于子组件错误而影响到整个页面不能使用的情况出现。解决方法是利用react的一个生命周期 getDerivedStateFromError
我们先来看一下案例,现在存在有Parent组件和Child组件:

Parent组件:
export default class Parent extends Component {state = {hasError:''}static getDerivedStateFromError(err){return {hasError: err}}render() {return (<div><h2>我是父组件</h2><Child/></div>)}
}
Child组件:
export default class Child extends Component {state = {person:[{name:'小明',age:10},{name:'大明',age:31},{name:'小红',age:16},]}render() {return (<div><h2>我是子组件</h2>{this.state.person.map(ele=>{return <li>{ele.name}--{ele.age}</li>})}</div>)}
}

页面上显示的效果如下:


errorBoundary演示用例1

组件中state的数据往往是通过请求后台返回回来的,如果说后台发生意外,传来的数据格式有问题,如果没有合理的解决这个问题,页面可能就直接用不了了。

export default class Child extends Component {state = {person: 'hh'}render() {return (<div><h2>我是子组件</h2>{this.state.person.map(ele=>{return <li>{ele.name}--{ele.age}</li>})}</div>)}
}
errorBoundary演示用例2

由于返回的数据有问题,使得原先的代码逻辑判断发生了错误,遇到这种情况,我们会希望把错误缩小到当前组件上,而不会对父组件以及其他组件的使用造成干扰。这时,我们就可以使用 getDerivedStateFromError来对子组件的错误进行捕获和限制。

给父组件加上钩子
export default class Parent extends Component {state = {hasError:''}static getDerivedStateFromError(err){return {hasError: err}}render() {return (<div><h2>我是父组件</h2>{this.state.hasError ? '网络不通畅,请稍后再试...':<Child/>}</div>)}
}

getDerivedStateFromError会捕获到子组件传递的错误,我们可以利用这个特性,对组件的显示进行判断。
需要注意的是,要想更好的观察错误边界这个效果,最好是打包后在服务器上面看效果。(在开发模式下,错误边界不起作用)。

errorBoundary演示用例3

我们可以看到,此时虽然子组件发生错误,但还是不影响页面的正常使用。另外,错误边界只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误。

八、Hook

我们知道,函数式组件由于无法使用this,所以也就不能像类式组件一样使用state和ref等属性。但是在React16.8 之后,官方推出了3个hook,使得函数式组件也可以像类式组件一般使用对应的属性以及常用的生命周期函数:

(1). State Hook: React.useState(): 可以使用state
(2). Effect Hook: React.useEffect(): 可以模拟生命周期钩子
(3). Ref Hook: React.useRef(): 可以使用ref
(一)State Hook 钩子
export default function Demo() {function add(){}return (<div><h2>当前总和为:???</h2><button onClick={add}>点我+1</button></div>)
}

我们想要赋予给函数式组件Demo一个state属性count,此时我们就可以这样实现:
使用React.useState()方法,我们可以传入对应属性的初始值,方法会返回一个数组,第一个参数是当前属性的值,第二个参数是修改这个属性的方法,我们可以在后续使用的时候,具体来设置方法的逻辑。

export default function Demo() {const [count,setCount] = React.useState(0);function add(){// setCount(count+1);  setCount的第一种写法setCount(count => count+1)}return (<div><h2>当前总和为:???</h2><button onClick={add}>点我+1</button></div>)
}
(二)Effect Hook

Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)。Effect Hook算是三个Hook之中较为复杂的一个了,我们可以用它来模拟componentDidMountcomponentDidUpdatecomponentWillUnmount这三个生命周期函数。
我们现在在上个案例的基础上再新增一个功能:每隔1秒钟,将count的值进行+1,如果是放在类式组件中,我们很容易就会想到使用componentDidMount来调用一个定时器,但是在函数式组件中,由于没有生命周期钩子函数,所以我们需要用React.useEffect()来实现我们的代码。

export default function Demo() {const [count,setCount] = React.useState(0);// 使用 Ref Hook,用法和React.createRef()一样const myRef = React.useRef();React.useEffect(()=>{let timer = setInterval(()=>{setCount(count => count+1);},1000)},[])function add() {// setCount(count+1);  setCount的第一种写法setCount(count => count+1)}return (<div><input type="text" ref={myRef}/><h2>当前总和为:{count}</h2><button onClick={add}>点我+1</button></div>)
}

userEffect需要传入2个参数,第一个相当于是组件加载好后执行的函数,第二个是指定具体监测的state
当第二个参数为空数组时,表示不监测任何一个state,即组件只加载一次,相当于是 componentDidMount钩子, 当第二个参数传入真实的state时,那么一旦监测的state状态发生改变,那么第一个函数就会调用,此时相当于是componentDidUpdate钩子 。同时,useEffect的return需要传入一个方法,在组件销毁的时候调用,相当于是 componentWillUnmount钩子。
我们现在再新增一个需求,利用useEffect的return方法,在卸载组件后停止运行定时器:

export default function Demo() {const [count,setCount] = React.useState(0);// 使用 Ref Hook,用法和React.createRef()一样const myRef = React.useRef();React.useEffect(()=>{let timer = setInterval(()=>{setCount(count => count+1);},1000)return ()=>{clearInterval(timer)}},[])function add() {// setCount(count+1);  setCount的第一种写法setCount(count => count+1)}function unmount(){ReactDOM.unmountComponentAtNode(document.getElementById('root'));}return (<div><input type="text" ref={myRef}/><h2>当前总和为:{count}</h2><button onClick={add}>点我+1</button><button onClick={unmount}>点击卸载组件</button></div>)
}

实际上,在点击卸载组件的按钮时,就会触发useEffect函数中return中定义的函数,成功停止计时器。

(三)Ref Hook

Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据,其实也就是赋予函数式组件使用类似于ref属性的功能。在上面的案例的基础上,我们在添加一个需求,新增一个文本框和按钮,当点击按钮时,把文本框的内容进行弹框显示:

    const [count,setCount] = React.useState(0);// 使用 Ref Hook,用法和React.createRef()一样const myRef = React.useRef();function add() {// setCount(count+1);  setCount的第一种写法setCount(count => count+1)}function show(){alert(myRef.current.value);}return (<div><input type="text" ref={myRef}/><h2>当前总和为:{count}</h2><button onClick={add}>点我+1</button><button onClick={show}>点击提示文本框内容</button><br/></div>)
}
说在最后:

本篇文章的代码已经放在了码云上,有需要的可以通过下面的链接下载:
https://gitee.com/moutory/react-extension

最后编辑于:2024-12-10 21:53:25


喜欢的朋友记得点赞、收藏、关注哦!!!

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

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

相关文章

【开源免费】基于SpringBoot+Vue.JS房屋租赁管理系统(JAVA毕业设计)

本文项目编号 T 091 &#xff0c;文末自助获取源码 \color{red}{T091&#xff0c;文末自助获取源码} T091&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

netcore 集成Prometheus

一、安装包 <ItemGroup><PackageReference Include"prometheus-net" Version"8.2.1" /><PackageReference Include"prometheus-net.AspNetCore" Version"8.2.1" /> </ItemGroup> 二、添加代码 #region Pro…

CLION中运行远程的GUI程序

在CLION中运行远程GUI程序&#xff0c;很有可能会遇到下面错误 Gtk-WARNING **: cannot open display: 这是因为远程的GUI程序不能再本地机器上显示。这个问题一般有两种解决方法 通过SSH的ForwardX11的方法&#xff0c;就是将远程的GUI程序显示到本地机器上&#xff0c;一般在…

datasets 笔记:加载数据集(基本操作)

参考了huggingface的教程 1 了解数据集基本信息&#xff08; load_dataset_builder&#xff09; 在下载数据集之前&#xff0c;通常先快速了解数据集的基本信息会很有帮助。数据集的信息存储在 DatasetInfo 中&#xff0c;可能包括数据集描述、特征和数据集大小等信息。&…

Java期末复习暨学校第十三次上机课作业

Java期末复习暨学校第十三次上机课作业&#xff1a; &#xff08;1&#xff09;&#xff1a;掌握正则表达式的使用 第一题&#xff1a; 第13行代码为正则表达式&#xff0c;中国内地的手机号必须是11个数字&#xff1a; &#xff08;1&#xff09; ^1&#xff1a;是该电话号码…

aosp15 - Activity生命周期切换

本文探查的是&#xff0c;从App冷启动后到MainActivity生命周期切换的系统实现。 调试步骤 在com.android.server.wm.RootWindowContainer#attachApplication 方法下断点&#xff0c;为了attach目标进程在com.android.server.wm.ActivityTaskSupervisor#realStartActivityLock…

【libuv】Fargo信令1:client发connect消息给到server

tcp 单机测试,进行模拟 (借助copilot实现) 【Fargo】28:字节序列client发connect消息给到serverserver 收到后回复ack给到客户端程序借助copilot实现。项目构建 Console依赖于Halo.dll提供的api,Halo 依赖于 Immanuel, 运行效果 遗留问题 客户端似乎么有逻辑收到ack做处理各…

libmodbus安装使用

要配置和编译 libmodbus&#xff0c;您需要确保安装了所有必要的依赖项&#xff0c;并按照正确的步骤进行操作。以下是详细的环境配置和编译指南&#xff0c;适用于不同的操作系统。 1. Linux (Debian/Ubuntu) 安装依赖项 首先&#xff0c;确保您的包列表是最新的&#xff1…

猫咪睡眠:萌态背后的奥秘与启示

猫咪的睡眠&#xff0c;犹如一本充满趣味与奥秘的小书&#xff0c;每一页都写满了它们独特的习性与本能。 猫咪堪称 “睡眠大师”&#xff0c;睡眠时间之长令人咋舌&#xff0c;一天中大约有 12 - 16 个小时在梦乡中度过&#xff0c;幼猫和老年猫甚至能睡更久。它们似乎深谙放…

关于小程序内嵌h5打开新的小程序

关于小程序内嵌h5打开新的小程序 三种方式 https://juejin.cn/post/7055551463489011749 只依赖于h5本身的就是 https://huaweicloud.csdn.net/64f97ebb6b896f66024ca16c.html https://juejin.cn/post/7055551463489011749 navigateToMiniProgram 故小程序webview里的h5无法…

免费GIS工具箱:轻松将glb文件转换成3DTiles文件

在GIS地理信息系统领域&#xff0c;GLB文件作为GLTF文件的二进制版本&#xff0c;主要用于3D模型数据的存储和展示。然而&#xff0c;GLB文件的使用频率相对较低&#xff0c;这是因为GIS系统主要处理的是地理空间数据&#xff0c;如地图、地形、地貌、植被、水系等&#xff0c;…

音视频入门基础:MPEG2-TS专题(21)——FFmpeg源码中,获取TS流的视频信息的实现

一、引言 通过FFmpeg命令可以获取到TS文件/TS流的视频压缩编码格式、色彩格式&#xff08;像素格式&#xff09;、分辨率、帧率信息&#xff1a; ./ffmpeg -i XXX.ts 本文以H.264为例讲述FFmpeg到底是从哪个地方获取到这些视频信息的。 二、视频压缩编码格式 FFmpeg获取TS文…

BenchmarkSQL使用教程

1. TPC-C介绍 Transaction Processing Performance Council (TPC) 事务处理性能委员会&#xff0c;是一家非盈利IT组织&#xff0c;他们的目的是定义数据库基准并且向产业界推广可验证的数据库性能测试。而TPC-C最后一个C代表的是压测模型的版本&#xff0c;在这之前还有TPC-A、…

火山引擎发布数据飞轮 2.0,AI 重塑企业数据消费

12 月 18 日&#xff0c;在 2024 冬季火山引擎 FORCE 原动力大会上&#xff0c;火山引擎数智平台&#xff08;VeDI&#xff09;正式升级发布数据飞轮 2.0 模式。 延续去年 4 月发布的数据飞轮“以数据消费促资产建设&#xff0c;以数据消费助业务发展”的核心内涵&#xff0c;…

LLaMA-Factory 单卡3080*2 deepspeed zero3 微调Qwen2.5-7B-Instruct

环境安装 git clone https://gitcode.com/gh_mirrors/ll/LLaMA-Factory.git 下载模型 pip install modelscope modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir /root/autodl-tmp/models/Qwen/Qwen2.5-7B-Instruct 微调 llamafactory-cli train \--st…

合并比对学习资料

目录 ContractComparison已开源: ContractComparison已开源: GitHub - UnstoppableCurry/ContractComparison: Comparison of General Chinese Contracts with OCR Pytorch

全速下载 50M/S,不限速下载就是香

近几年来虽说各大网盘层出不穷&#xff0c;各有乾坤&#xff0c;而这其中某些网盘对于网速限制非常严重&#xff0c;这也是很多小伙伴一直吐槽的点&#xff0c;并且某些网盘下载文件还需要安装客户端&#xff0c;并且每家的限速方式不同&#xff0c;有的限速取决于文件大小&…

回归预测 | MATLAB实现CNN-BiGRU-Attention卷积神经网络结合双向门控循环单元融合注意力机制多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiGRU-Attention卷积神经网络结合双向门控循环单元融合注意力机制多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiGRU-Attention卷积神经网络结合双向门控循环单元融合注意力机制多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效…

RunCam WiFiLink连接手机图传测试

RunCam WiFiLink中文手册从这里下载 一、摄像头端 1.连接天线&#xff08;易忘&#xff09; 2.打开摄像头前面的盖子&#xff08;易忘&#xff09; 3.接上直流电源&#xff0c;红线为正&#xff0c;黑线为负 4.直流电源设置电压为14v&#xff0c;电流为3.15A&#xff0c; 通…

AI的进阶之路:从机器学习到深度学习的演变(二)

AI的进阶之路&#xff1a;从机器学习到深度学习的演变&#xff08;一&#xff09; 三、机器学习&#xff08;ML&#xff09;&#xff1a;AI的核心驱动力 3.1 机器学习的核心原理 机器学习&#xff08;Machine Learning, ML&#xff09;突破了传统编程的局限&#xff0c;它不再…