在少数情况下,需要在常规数据流外强制修改子元素。被修改的子元素可以是 React 组件实例,或者是一个 DOM 元素。在这种情况下,React 提供了解决办法。
一. 何时使用 Refs
- 处理focus、文本选择或者媒体播放
- 触发强制动画
- 集成第三方DOM库
如果可以通过声明式实现,就尽量避免使用 refs 。
不要过度使用 Refs,尽量在组件层使用state,因为state更为清晰。
二. 在 DOM 元素上添加 Ref
React 支持给任何组件添加特殊属性。ref
属性接受回调函数,并且当组件 装载(mounted) 或者 卸载(unmounted) 之后,回调函数会立即执行。
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// 通过使用原生API,显式地聚焦text输入框
this.textInput.focus();
}
render() {
// 在实例中通过使用`ref`回调函数来存储text输入框的DOM元素引用(例如:this.textInput)
return (
<div>
<input
type="text"
ref={input => this.textInput = input; } />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
使用 ref 回调只是为了在类上设置一个属性,是访问 DOM 元素的常见模式。
三. 为 类(Class) 组件添加 Ref
当ref
属性用于类(class)声明的自定义组件时,ref
回调函数收到的参数是装载(mounted)的组件实例。例如,如果我们想包装CustomTextInput
组件,实现组件在 装载(mounted) 后立即点击的效果:
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}
注:这种方式仅对以类(class)声明的component有效:
class CustomTextInput extends React.Component {
// ...
}
四. Refs 与 函数式组件
不能在函数式组件上使用 ref 属性,因为它们没有实例:
function MyFunctionalComponent() {
return <input />;
}
class Parent extends React.Component {
render() {
// 这里 *不会* 执行!
return (
<MyFunctionalComponent
ref={(input) => { this.textInput = input; }} />
);
}
}
但是可以在函数式组件内部使用 ref来引用一个 DOM 元素或者 类(class)组件:
function CustomTextInput(props) {
// textInput必须在这里声明,所以 ref 回调可以引用它
let textInput = null;
function handleClick() {
textInput.focus();
}
return (
<div>
<input
type="text"
ref={(input) => { textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
);
网友评论