1. 主页 > 大智慧

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>鈥嬶細

  1. useRef鍒濆鍖栨椂瑕佺粰null锛屼笉鐒朵細鎶ラ敊
  2. current灞炴€ф墠鏄湡姝g殑DOM寮曠敤
  3. 淇敼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>
  1. 鈥?strong>鈥嬪湪娓叉煋闃舵璁块棶current鈥?/strong>鈥?/p>

    javascript澶嶅埗
    // 閿欒绀鸿寖锛?/span>
    function BadExample() {
      const divRef = useRef(null)
      console.log(divRef.current) // 杩欓噷姘歌繙鏄痭ull
      return <div ref={divRef} />
    }
  2. 鈥?strong>鈥嬪繕璁版竻鐞嗗壇浣滅敤鈥?/strong>鈥?br/> 鐢╮ef淇濆瓨瀹氭椂鍣ㄦ椂锛?/p>

    javascript澶嶅埗
    function Timer() {
      const timerRef = useRef()
    
      useEffect(() => {
        timerRef.current = setInterval(() => {
          // do something
        }, 1000)
        
        return () => clearInterval(timerRef.current)
      }, [])
    }
  3. 鈥?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>

本文由嘻道妙招独家原创,未经允许,严禁转载