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;
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(_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