1.2 React Ref API
Ref的功能强大,它能够让组件与DOM元素,或类组件与其父级之间建立直接联系。总体而言,使用Ref出于以下3个目的。
❑ 访问DOM元素。
❑ 访问组件的实例。
❑ 将Ref作为mutable数据的存储中心。
1.创建Ref
创建Ref有两种方式,分别为useRef和React.createRef。useRef是一种Hooks,只能在函数组件中使用,更多的Hooks在后文介绍。React.createRef的使用位置不限,但不要在函数组件中使用它,如果在函数组件中用它创建Ref,那么函数组件每一次重新渲染都会创建新的Ref。下面的代码显示了React.createRef、useRef和Ref的数据类型。
Ref由React.createRef或useRef函数返回,从上述代码可以看出Ref有两种数据类型,分别是MutableRefObject和RefObject,这两种类型都有current字段,类型参数T用于注释current的类型。下面的代码演示了如何创建Ref。
2.访问DOM元素
要想通过Ref访问DOM元素,必须将Ref绑定到浏览器内置的组件上,等组件装载之后使用ref.current字段访问DOM元素。下面的代码演示了如何用Ref访问input元素使它获得焦点。
上述代码用useRef创建Ref,将Ref属性绑定到input元素上,底层的input元素被赋值给inputRef.current,使用inputRef.current直接操作DOM元素。
3.访问组件的实例
将Ref属性绑定到类组件上,通过ref.current能访问到类组件的实例,由于函数组件没有实例,所以不能在函数组件上绑定Ref属性。下面的代码演示了如何在父组件中通过Ref访问子组件实例以及调用子组件的方法。
上述代码通过Ref使RefUse组件与ChildCom组件直接联系,在RefUse中调用ChildCom的实例方法修改组件的状态。
注意
上述两个示例都在函数组件中用useRef创建Ref,在类组件中用React.createRef创建Ref的方法与此相同。
4.将Ref作为mutable数据的存储中心
将Ref作为mutable数据的存储中心,使用场景主要是函数组件,这是因为函数组件每一次重新渲染都会执行函数体,使函数体中的各个变量被重新创建。如果函数体中声明了一些只用于缓存的数据,即不会导致组件重新渲染的变量,那么将这些数据放在Ref中能避免它们被反复创建。将Ref作为mutable数据的存储中心的示例代码如下。
将Ref作为mutable数据的存储中心,不需要将它绑定到React element上,创建之后能直接使用,修改mutableRef.current的值,组件不会重新渲染。
5.总结
Ref的功能很强大,但不要滥用。在这里回顾一下使用Ref的3个目的。
❑ 访问DOM元素。请记住,React是基于数据驱动的,也可以理解为是基于状态驱动的,在React程序中不推荐直接访问DOM元素。
❑ 访问组件实例。通过Ref在父组件中获得子组件的实例,让父子组件建立直接联系,会让状态变更变得混乱,父子组件之间的交互应该通过props进行,遵循单向数据流原则。
❑ 在函数组件中创建Ref,将它作为mutable数据的存储中心,有它的用武之地,但在类组件中大可不必如此。