# Refs 和 DOM
在典型的 React 数据流中,[props](https://facebook.github.io/react/docs/components-and-props.html) 是父组件影响子组件的唯一方式。要修改一个子组件,可以使用新的 props 重新渲染它。然而,有一些情况你需要在典型的数据流之外命令式修改一个子组件。要被修改的子组件应该是一个 React 组件的实例,或者它应该是一个 DOM 元素。这两种情况,React 提供了一个 安全舱。
## ref 回调属性
React 支持一个特定的属性,你可以用来连接到任何组件。ref 属性带有一个回调函数,回调函数在组件被装载或者卸载之后立即执行。
当 ref 属性用于在一个 HTML 元素上,ref 回调接受底层的 DOM 元素作为它的参数。例如,这段代码使用了 ref 回调来存储一个 对于 一个 DOM 节点的引用:
~~~
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in this.textInput.
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
~~~
当组件被安装后,React 将会在 DOM 元素上调用 ref 回调,并在组件卸载时传递 null 进行调用。
使用 ref 回调只要设置类的属性为一个一般模式来访问 DOM 元素。如果你正确的使用 this.refs.myRefName 来访问 refs,我们建议使用 这个模式替代。
当 ref 属性用在一个自定义组件上,ref 回调接受安装的组件实例作为它的参数。例如,如果我们想要包装 CustomTextInput 来模拟它在装载之后立即被点击:
~~~
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}
~~~
你不能使用 ref 属性在功能组件上,因为它们没有实例。然而,你可以使用 ref 属性在一个功能组件的 render 函数中:
~~~
function CustomTextInput(props) {
// textInput must be declared here so the ref callback can refer to it
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>
);
}
~~~
## 不要过度使用 refs
你首先的倾向可能是用 refs 来”使某事情发生“。如果说这个情况,用一些时间思考,关于 state 应该被在组件层级中的哪里拥有。通常,适当的位置拥有 state 是在一个更高的层级上,将变得清晰。查看[状态提升](https://facebook.github.io/react/docs/lifting-state-up.html)中关于这个的例子。