1.refs使用场景
在某些情况下,我们需要在典型数据流之外强制修改子组件,被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素,例如:
- 管理焦点,文本选择或媒体播放。
如下面这样:
focusTextInput() {
// 直接使用原生 API 使 text 输入框获得焦点
// 注意:我们通过 "current" 来访问 DOM 节点
this.textInput.current.focus();
}
- 触发强制动画。
- 集成第三方 DOM 库。
2.如何设置refs
(1)React.createRef()
。
- 创建refs
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
- 访问refs
当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。
const node = this.myRef.current;
ref 的值根据节点的类型而有所不同:
- 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
- 当 ref 属性用于自定义 class 组件时,ref 对象接收
组件的挂载实例
作为其 current 属性。 你不能在函数组件上使用 ref 属性,因为他们没有实例
。
(2)回调refs
使用 回调 refs 需要将回调函数
传递给 React元素 的 ref 属性
。这个函数接受 React 组件实例 或 HTML DOM 元素作为参数,将其挂载到实例属性上。示例:
import React from 'react';
export default class MyInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = null;
this.setTextInputRef = (ele) => {
this.inputRef = ele;
}
}
componentDidMount() {
this.inputRef && this.inputRef.focus();
}
render() {
return (
<input type="text" ref={this.setTextInputRef}/>
)
}
}
React 会在组件挂载时,调用 ref 回调函数并传入 DOM元素(或React实例),当卸载时调用它并传入 null。在 componentDidMount 或 componentDidUpdate 触发前,React 会保证 Refs 一定是最新的。
3.子组件未被connect()包装成容器组件
就比如下面这个CustomTextInput
组件,用 ref 的 current 属性中被访问。
class AutoFocusTextInput extends React.Component {
constructor(props) {
super(props);
this.textInput = React.createRef();
}
componentDidMount() {
this.textInput.current.focusTextInput();
}
render() {
return (
<CustomTextInput ref={this.textInput} />
);
}
}
CustomTextInput
组件
class CustomTextInput extends React.Component {
// ...
}
4.子组件被connect()包装成了容器组件,用current访问不行了。
原因是:ref上没有current属性了。
- 如何获取呢?
connect 有四个参数,如果我们想要在父组件中子组件(木偶组件)的实例,那么需要设置第四个参数options
的withRef 为 true
。随后可以在父组件中通过容器组件实例的 getWrappedInstance()
方法获取到木偶组件(被包装的组件)的实例。
AutoComplete子组件
export default connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })(AutoComplete);
Filter父组件
<AutoComplete
getInputValue={getInputValue}
options={options}
getData={getData}
updateSelect={this.updateSelect}
ref = {ref => this.triggerEmptyValue = ref}
/>
Filter父组件中获取AutoComplete组件实例,并且调用其方法
this.triggerEmptyValue.getWrappedInstance().emptyInputValue();