概述
很久之前就知道refs,感觉好神秘,恰好今天突然发现字符串形式的ref在官网不推荐使用了,于是好好总结一下ref的用法,供以后开发时参考,相信对其他人也有用。
参考资料:
refs
在react数据流中,可以通过props,refs和Context来访问其它组件的属性,其中利用refs可以在数据流外强制修改组件实例。
需要注意的是,以前是通过给refs赋一个string,比如textInput,然后就可以通过this.refs.textInput来访问DOM节点,示例如下:
import React, { Component } from 'react';class NoControl extends Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(e) { e.preventDefault(); console.log(this.refs.name); } render() { return(); }}export default NoControl;
但是官网不推荐使用这种形式使用refs了,并且这种方法在未来的版本可能会被移除。官方建议使用回调的形式代替这种使用方式。
refs的基本用法
一般说来,我们需要在constructor里面初始化一个ref,然后就能在return里面用了,示例如下:
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return ; }}
上面的this.myRef有一个current属性,它的值取决于下面三种情况:
- 如果ref属性被用于html元素,那么它的值是底层DOM元素。
- 如果ref属性被用于自定义类组件,那么它的值是已挂载的这个自定义类组件的实例。
- 函数式组件没有ref属性。
另外,通过ref我们还可以调用这个自定义类组件的方法,示例如下:
import React, { Component } from 'react';class CustomInput extends Component { constructor(props) { super(props); this.handleFocus = this.handleFocus.bind(this); this.myRef = React.createRef(); } handleFocus(e) { this.myRef.current.focus(); } render() { return( ) }}class NoControl extends Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.myRef = React.createRef(); } handleSubmit(e) { e.preventDefault(); this.myRef.current.handleFocus(); } render() { return(
refs的回调用法
由于refs里面的回调函数会在组件创建的时候自动生成。所以可以利用refs的回调用法,在组件创建的时候获得这个组件的一些信息,比如获得焦点等。示例如下:
import React, { Component } from 'react';class NoControl extends Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.setElement = this.setElement.bind(this); this.myInput = null; } handleSubmit(e) { e.preventDefault(); this.forceUpdate(); } setElement(element) { this.myInput = element; } componentDidMount() { this.myInput.focus(); } render() { return(); }}export default NoControl;
refs转发
在使用HOC(高阶组件)的时候,我们是用一个类组件来对普通组件进行封装的,这个时候怎么获得里面这个普通组件的ref呢。
react官方提供了React.forwardRef这个api来实现。示例如下:
//NoControl.jsximport React, { Component } from 'react';import CustomInput from './CustomInput';class NoControl extends Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.myRef = React.createRef(); } handleSubmit(e) { e.preventDefault(); this.myRef.current.handleFocus(); this.forceUpdate(); } render() { return(
需要注意的是,forwardRef有第二个参数ref,然后它被React.forwardRef这个api封装,最后返回Component类组件。