1 是什么
Refs 是在 React 中获取节点(原生 DOM 或 React 组件)实例的方式。可以通过 Refs 来获取节点实例的引用,通过操作此引用达到操作节点的目的。
2 解决什么问题
Refs 主要用来解决需要操作节点的场景,如:
- 管理子节点焦点、文本选择
- 强制动画
- 集成第三方 DOM 库
3 使用方法
3.1 createRef
React.createRef 是 React 16.3 版本引入的创建 Refs 的方法。
3.1.1 创建 Refs
通过 React.createRefs() 方法可以创建 Refs。
1 2 3 4 5 6 7 8 9 10 11
| class MyComponent extends React.Component { constructor(props) { super(props); // 1、在组件中调用 createRef 函数创建 Refs 变量 this.myRef = React.createRef(); } render() { // 2、使用 ref(此属性名固定) 属性将 Refs 变量和节点关联起来 return <div ref={this.myRef} />; } }
|
3.1.2 访问 Refs
通过 Refs 变量的 current 属性可以访问节点的引用。
1
| const node = this.myRef.current;// 此时 node 就是节点实例的引用
|
当组件挂载时,this.myRef.current 会被赋值为节点实例。
当组件被卸载时,this.myRef.current 会被赋值为 null。
3.1.3 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class CustomTextInput extends React.Component { constructor(props) { super(props); //1、创建 Refs 变量 this.textInput this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this); }
focusTextInput() { // 3、通过 this.textInput.current 属性访问节点实例 this.textInput.current.focus(); }
render() { // 2、通过给节点配置 ref 属性,将节点实例关联到 this.textInput return ( <div> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
|
3.2 callback Refs
callback Refs 是指通过给节点的 ref 属性传递回调函数来获取节点实例。
3.2.1 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class CustomTextInput extends React.Component { constructor(props) { super(props);
this.textInput = null;
this.setTextInputRef = element => { //2、回调函数会在节点挂载和卸载时被调用 // 节点的实例被作为参数(如 element)传给回调,卸载时 element 的值为 null this.textInput = element; };
this.focusTextInput = () => { // 3、使用引用来操作节点 if (this.textInput) this.textInput.focus(); }; }
componentDidMount() { // 组件挂载后,让文本框自动获得焦点 this.focusTextInput(); }
render() { // 1、给节点的 `ref` 属性配置回调函数 this.setTextInputRef return ( <div> <input type="text" ref={this.setTextInputRef} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
|
3.2.2 注意
ref 回调可以在组件间传递,进而可以解决嵌套组件间 ref 传递问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function CustomTextInput(props) { // ref 属性值通过 props 从外部传递进来 return ( <div> <input ref={props.inputRef} /> </div> ); }
class Parent extends React.Component { render() { return ( <CustomTextInput inputRef={el => this.inputElement = el} /> ); } }
|
3.3 String Refs(过时的 API)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class CustomTextInput extends React.Component { constructor(props) { super(props); this.focusTextInput = this.focusTextInput.bind(this); }
focusTextInput() { // 2、在父节点中通过 this.refs.myInput 属性访问子节点实例 this.refs.myInput.focus(); }
render() { // 1、通过给子节点配置 ref 属性,值为字符串 myInput return ( <div> <input type="text" ref="myInput" /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
|
如果目前还在使用 this.refs.textInput
这种方式访问 refs ,建议用 callback refs 或 createRefs 的方式代替,String 类型的 Refs 在未来版本可能将会被移除。
4 注意
1、默认情况下,不能在函数组件上使用 ref 属性,因为它没有实例。可以通过 forwardRef 创建函数组件,进而使其可以接收 ref 属性,或者将函数组件转化为 class 组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function MyFunctionComponent() { return <input />; }
class Parent extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } render() { // This will *not* work! return ( <MyFunctionComponent ref={this.textInput} /> ); } }
|