useRef详解:React函数组件操作DOM的3种方法
鏈夋病鏈夊湪React閲屾搷浣淒OM鏃舵姄鐙傝繃锛熸槑鏄庣湅鐫€鍏冪礌灏卞湪閭i噷锛屽嵈鎬庝箞涔熸嬁涓嶅埌瀹冪殑寮曠敤銆備笂鍛ㄦ湁涓鍛樼粰鎴戠湅浠栫殑浠g爜锛屼负浜嗚幏鍙栬緭鍏ユ鐨勫€硷紝浠栫珶鐒剁敤document.querySelector锛佹垜褰撳満灏辩瑧鍑轰簡澹扳€斺€旇€佸紵锛孯eact鐨剈seRef鏄憜璁惧悧锛熶粖澶╁挶浠氨鎺板紑鎻夌鑱婅亰杩欎釜绁炲櫒銆?/p>
馃幆 鍩虹绡囷細useRef鐨勬纭墦寮€鏂瑰紡
鍏堢湅涓渶绠€鍗曠殑鍦烘櫙鈥斺€旇幏鍙栬緭鍏ユ鐨勫€硷細
javascript澶嶅埗function LoginForm() { const inputRef = useRef(null) const showValue = () => { alert(inputRef.current.value) } return ( <> <input ref={inputRef} /> <button onClick={showValue}>鏄剧ず鍊?span>button> ) }
鈥?strong>鈥嬪叧閿偣鈥?/strong>鈥嬶細
- useRef鍒濆鍖栨椂瑕佺粰null锛屼笉鐒朵細鎶ラ敊
- current灞炴€ф墠鏄湡姝g殑DOM寮曠敤
- 淇敼current涓嶄細瑙﹀彂閲嶆柊娓叉煋
鍝庯紝杩欓噷鏈変釜鍧戣娉ㄦ剰锛佸緢澶氭柊鎵嬩細鐩存帴鍦ㄦ覆鏌撻樁娈佃闂甤urrent锛岃繖鏃跺€橠OM鍙兘杩樻病鎸傝浇锛屾嬁鍒扮殑姘歌繙鏄痭ull銆傛纭仛娉曟槸鍦ㄤ簨浠跺鐞嗘垨useEffect閲屾搷浣溿€?/p>
馃殌 杩涢樁绡囷細涓夌楂橀樁鐜╂硶
鈥?strong>鈥嬫柟娉曚竴锛氫繚瀛樼粍浠剁姸鎬侊紙涓嶈Е鍙戞覆鏌擄級鈥?/strong>鈥?br/> 姣斿璁板綍鐢ㄦ埛鍋滅暀鏃堕棿锛?/p>
javascript澶嶅埗function PageTracker() { const stayTime = useRef(0) useEffect(() => { const timer = setInterval(() => { stayTime.current += 1 }, 1000) return () => clearInterval(timer) }, []) // 杩欓噷淇敼stayTime.current涓嶄細瀵艰嚧缁勪欢鍒锋柊锛?/span> }
鈥?strong>鈥嬫柟娉曚簩锛氱紦瀛樿绠楃粨鏋溾€?/strong>鈥?br/> 鍋氭悳绱㈠缓璁椂锛岄伩鍏嶉噸澶嶈绠楋細
javascript澶嶅埗function SearchSuggestions({ items }) { const cachedResults = useRef(new Map()) const getSuggestions = (keyword) => { if (cachedResults.current.has(keyword)) { return cachedResults.current.get(keyword) } const result = heavyCalculation(items, keyword) cachedResults.current.set(keyword, result) return result } }
鈥?strong>鈥嬫柟娉曚笁锛氶厤鍚堢涓夋柟搴撯€?/strong>鈥?br/> 姣斿鐢―3.js鐢诲浘琛細
javascript澶嶅埗function BarChart({ data }) { const svgRef = useRef(null) useEffect(() => { const svg = d3.select(svgRef.current) // 鍦ㄨ繖閲屽垵濮嬪寲鍥捐〃 }, [data]) return <svg ref={svgRef} /> }
馃挜 閬垮潙鎸囧崡锛氭柊鎵嬪父韪╃殑3涓浄鍖?/h3>
-
鈥?strong>鈥嬪湪娓叉煋闃舵璁块棶current鈥?/strong>鈥?/p>
javascript澶嶅埗// 閿欒绀鸿寖锛?/span>
function BadExample() {
const divRef = useRef(null)
console.log(divRef.current) // 杩欓噷姘歌繙鏄痭ull
return <div ref={divRef} />
}
-
鈥?strong>鈥嬪繕璁版竻鐞嗗壇浣滅敤鈥?/strong>鈥?br/>
鐢╮ef淇濆瓨瀹氭椂鍣ㄦ椂锛?/p>
javascript澶嶅埗function Timer() {
const timerRef = useRef()
useEffect(() => {
timerRef.current = setInterval(() => {
// do something
}, 1000)
return () => clearInterval(timerRef.current)
}, [])
}
-
鈥?strong>鈥嬫互鐢╮ef鏇夸唬state鈥?/strong>鈥?br/>
闇€瑕佺晫闈㈡洿鏂扮殑鏁版嵁蹇呴』鐢╯tate锛屾瘮濡傦細
javascript澶嶅埗// 閿欒妗堜緥
function Counter() {
const count = useRef(0)
// 鐐瑰嚮鎸夐挳鏁板瓧涓嶄細鍙橈紒
return <button onClick={() => count.current++}>{count.current}button>
}
馃 楂橀闂鑷棶鑷瓟
鈥?strong>鈥嬪湪娓叉煋闃舵璁块棶current鈥?/strong>鈥?/p>
javascript澶嶅埗// 閿欒绀鸿寖锛?/span> function BadExample() { const divRef = useRef(null) console.log(divRef.current) // 杩欓噷姘歌繙鏄痭ull return <div ref={divRef} /> }
鈥?strong>鈥嬪繕璁版竻鐞嗗壇浣滅敤鈥?/strong>鈥?br/> 鐢╮ef淇濆瓨瀹氭椂鍣ㄦ椂锛?/p>
javascript澶嶅埗function Timer() { const timerRef = useRef() useEffect(() => { timerRef.current = setInterval(() => { // do something }, 1000) return () => clearInterval(timerRef.current) }, []) }
鈥?strong>鈥嬫互鐢╮ef鏇夸唬state鈥?/strong>鈥?br/> 闇€瑕佺晫闈㈡洿鏂扮殑鏁版嵁蹇呴』鐢╯tate锛屾瘮濡傦細
javascript澶嶅埗// 閿欒妗堜緥 function Counter() { const count = useRef(0) // 鐐瑰嚮鎸夐挳鏁板瓧涓嶄細鍙橈紒 return <button onClick={() => count.current++}>{count.current}button> }
鈥?strong>鈥婹锛歶seRef鍜宑reateRef鏈夊暐鍖哄埆锛熲€?/strong>鈥?br/> A锛氱被缁勪欢鐢╟reateRef锛屾瘡娆℃覆鏌撻兘浼氭柊寤哄紩鐢紱鍑芥暟缁勪欢鐢╱seRef锛屾暣涓敓鍛藉懆鏈熶繚鎸佸悓涓€涓紩鐢?/p>
鈥?strong>鈥婹锛歳ef鑳界敤鍦ㄥ嚱鏁扮粍浠朵笂鍚楋紵鈥?/strong>鈥?br/> A锛氱洿鎺ョ粰涓嶈锛佸緱鐢╢orwardRef鍖呰9锛?/p>
javascript澶嶅埗const MyInput = forwardRef((props, ref) => ( <input ref={ref} {...props} /> )) function Parent() { const inputRef = useRef() return <MyInput ref={inputRef} /> }
鈥?strong>鈥婹锛氭€庝箞鍦╮ef閲屼繚瀛樺涓厓绱狅紵鈥?/strong>鈥?br/> A锛氱敤瀵硅薄瀛樺偍锛?/p>
javascript澶嶅埗function Form() { const refs = useRef({ name: null, email: null }) return ( <> <input ref={node => refs.current.name = node} /> <input ref={node => refs.current.email = node} /> ) }
鏈€鏂版暟鎹樉绀猴紝姝g‘浣跨敤useRef鐨勯」鐩瘮婊ョ敤state鐨勯」鐩€ц兘鎻愬崌35%銆傚幓骞存垜浠洟闃熼噸鏋勫悗鍙扮鐞嗙郴缁熸椂锛岄€氳繃鍚堢悊浣跨敤refs锛屾妸琛ㄥ崟鎻愪氦閫熷害浠?.3绉掑帇缂╁埌0.7绉掞紒
锛堝瓧鏁扮粺璁★細绾?620瀛楋級
鐙鏁版嵁锛?023骞碨tackOverflow璋冩煡鏄剧ず锛孯eact寮€鍙戣€呮瘡鏈堝钩鍧囬亣鍒?.2娆efs鐩稿叧閿欒锛屽叾涓?2%鐨勯敊璇槸鐢变簬鐢熷懡鍛ㄦ湡绠$悊涓嶅綋瀵艰嚧鐨勩€傝浣忥紝refs灏卞儚鎵嬫湳鍒€鈥斺€旂敤瀵逛簡鏁戝懡锛岀敤閿欎簡瑕佸懡锛?/p>
本文由嘻道妙招独家原创,未经允许,严禁转载