useRef简单的使用
const usernameUseRef = useRef()
<input type="text" ref={
usernameRef} />
<button
onClick={
() => {
console.log(usernameRef.current.value)
}}
>
createRef和useRef区别
- createRef 它可以用在类组件和函数组件中,声明式不能给初始值
const usernameCreateRef = createRef()
- useRef 它只能使用在函数组件中,useRef它可以在声明时给初始值,但一般为null
const usernameUseRef = useRef(null)
- createRef每次重新渲染时都会创建一个ref对象,组件被重新渲染时它也会重新创建,但是因为类组件中它有生命周期,我可以在构造函数中创建这个ref,也就会执行一次。
- useRef第1次渲染时创建一个对象之后,再新渲染时,如果发现这个对象已经存在过不会再创建,它的性能更好一些,在函数组件中推荐使用useRef
测试:验证;
import React, {
createRef, useRef, useEffect, useState } from 'react';
const App = () => {
const usernameCreateRef = createRef();
const usernameuseRef = useRef();
const [value, setvalue] = useState(100)
if (!usernameCreateRef.current) {
usernameCreateRef.current = value;
}
if (!usernameuseRef.current) {
usernameuseRef.current = value;
}
return (
<div>
<hr />
<h1>
createRef:{
usernameCreateRef.current}
</h1>
<h1>
useRef:{
usernameuseRef.current}
</h1>
<hr />
<h1>
</h1>
<button onClick={
() => {
setvalue(v => v + 1)
}
}>++++</button>
</div>
);
}
export default App;
forwardRef完成类组件的绑定
- 如果ref对象绑定在自定义类组件中,则得到当前自定义类组件的实例,从而可以实现组件通信
- 如果ref直接绑定在自定义函数组件中,则不行,因为函数组件没有实例,所以会报错
- 函数组件如果你需要绑定ref,则需要通过它提供的一个顶层api方法来增强函数组件从而实现函数组件也可以绑定ref对象
React.forwardRef
- 直接使用ref的话就会报错
通过这个forwardRef
来包裹一下这个子组件就行。
就可以ref了,具体还得往下看。
import React, {
useRef,forwardRef } from 'react';
const Child = forwardRef((props,_ref) => {
return (
<div>
<h1 ref={
_ref}>子组件</h1>
</div>
);
})
const App = () => {
const ref = useRef();
return (
<div>
<Child ref={
ref}/>
<button onClick={
e=>{
console.log(ref.current);
}}>@@@@@</button>
</div>
);
}
export default App;
当然通过这个useref可以初始化的特性,ref也可以完成对组件的传值。
const ref = useRef(100);
const App = () => {
const ref = useRef(100);
return (
<div>
<Child ref={
ref}/>
<button onClick={
e=>{
ref.current++
console.log(ref.current);
}}>@@@@@</button>
</div>
);
}
export default App;
useImperativeHandle映射对象(透传)
useImperativeHandle 集合useRef和forwardRef 方法来模拟给函数组件绑定ref对象来得到子组件中对外暴露出来的方法或数据
useImperativeHandle(_ref,()=>{
return {
value,
changevalue,
childref
}
})
- 参数1:就是父组件传过来的ref对象
- 参数2:回调函数,返回一个对象,穿透给父组件的数据
import React, {
useRef,forwardRef, useState ,useImperativeHandle} from 'react';
const Child = forwardRef((props,_ref) => {
let [value,setValue] = useState();
const changevalue = (newvalue)=>{
setValue(newvalue)
}
const childref = useRef()
useImperativeHandle(_ref,()=>{
return {
value,
changevalue,
childref
}
})
return (
<div>
<h1>子组件</h1>
<input type="text" name="" id="" ref={
childref} value="123s"/>
<h2>{
value}</h2>
</div>
);
})
const App = () => {
const ref = useRef(100);
return (
<div>
<Child ref={
ref}/>
<hr />
<button onClick={
e=>{
// 获取到返回来的映射对象,操作子组件的内容
console.log(ref.current);
ref.current.changevalue("niupeng")
}}>@@@@@</button>
</div>
);
}
export default App;
useLayouEffect同步周期函数
import React, {
useLayoutEffect, useEffect } from 'react'
const App = () => {
// js事件循环中,同步优先于异步
// 异步
useEffect(()=>{
console.log('useEffect');
},[])
// 同步 如果你是操作dom来说,建议用它
useLayoutEffect(()=>{
console.log('useLayoutEffect');
document.title = '你好react'
},[])
return <div>
<h3>App组件</h3>
</div>
}
export default App