React函数式组件值之useRef()和useImperativeHandle()


一、useRef

  useRef共有两种用法,获取子组件的实例(只有类组件可用),在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx。

1,获取子组件实例

useRef 在使用的时候,可以传入默认值来指定默认值,需要使用的时候,访问 ref.current 即可访问到组件实例:

 1 // 使用 ref 子组件必须是类组件
 2 class Children extends PureComponent {  3  render () {  4     const { count } = this.props  5     return (  6       <div>{ count }</div>
 7  )  8  }  9 } 10 function App () { 11   const [ count, setCount ] = useState(0) 12   const childrenRef = useRef(null) 13   const onClick = useMemo(() => { 14     return () => { 15  console.log(childrenRef.current) 16       setCount((count) => count + 1) 17  } 18  }, []) 19   return ( 20     <div>
21  点击次数: { count } 22       <Children ref={childrenRef}  count={count}></Children>
23       <button onClick={onClick}>点我</button>
24     </div>
25  ) 26 }

2,类组件属性

  有些情况下,我们需要保证函数组件每次 render 之后,某些变量不会被重复申明,比如说 Dom 节点,定时器的 id 等等,在类组件中,我们完全可以通过给类添加一个自定义属性来保留,比如说 this.xxx, 但是函数组件没有 this,自然无法通过这种方法使用,有的朋友说,我可以使用useState 来保留变量的值,但是 useState 会触发组件 render,在这里完全是不需要的,我们就需要使用 useRef 来实现了,具体看下面例子:

 1 function App () {  2   const [ count, setCount ] = useState(0)  3   const timer = useRef(null)  4  let timer2  5   useEffect(() => {  6     let id = setInterval(() => {  7       setCount(count => count + 1)  8     }, 500)  9     timer.current = id 10     timer2 = id 11     return () => { 12  clearInterval(timer.current) 13  } 14  }, []) 15   const onClickRef = useCallback(() => { 16  clearInterval(timer.current) 17  }, []) 18   const onClick = useCallback(() => { 19  clearInterval(timer2) 20  }, []) 21   return ( 22     <div>
23  点击次数: { count } 24       <button onClick={onClick}>普通</button>
25       <button onClick={onClickRef}>useRef</button>
26     </div>
27  ) 28 }

二、useImperativeHandle

  useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值,说简单点就是,子组件可以选择性的暴露给副组件一些方法,这样可以隐藏一些私有方法和属性,官方建议,useImperativeHandle应当与 forwardRef 一起使用,具体如何使用看下面例子

 1 function Child (props, ref) {  2   const child = useRef()  3   const introduce = useCallback (() => {  4     console.log('i can sing, jump, rap, play basketball')  5  }, [])  6   useImperativeHandle(ref, () => ({introduce}));  7   return (  8     <div ref={child}> { props.count }</div>
 9  ) 10 } 11 const ChildChild = forwardRef(Child) 12 function App () { 13   const [ count, setCount ] = useState(0) 14   const childRef = useRef(null) 15   const onClick = useCallback (() => { 16     setCount(count => count + 1) 17  childRef.current.introduce() 18  }, []) 19   return ( 20     <div>
21  点击次数: { count } 22       <ChildChild ref={childRef}  count={count}></ChildChild>
23       <button onClick={onClick}>点我</button>
24     </div>
25  ) 26 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM