• 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 }
  • 相关阅读:
    Javascript DOM 编程艺术读书笔记16/03/25
    2014 Multi-University Contest 1.1 hdu4861 打表找规律
    汇编小记16/3/23
    汇编小记16/3/22
    hdoj 4940 强连通图
    Head FIRST HTML & CSS 16/03/17
    html&css一些有用的网站整理
    dosbox+debug 模拟dos
    汇编小记16/3/15
    解决windwos另存为,保存文件时无法选择“桌面”文件夹
  • 原文地址:https://www.cnblogs.com/guanghe/p/14178951.html
Copyright © 2020-2023  润新知