译者:小猿大圣
在典型的 React 数据流中, props 是父组件与子组件互动的唯一方法。 想要修改子组件,你要用新的props重新渲染它。 然而, 有些情况你必须在典型的React数据流之外强制修改子组件。被修改的子组件可以是一个React组件实例,也可以是一个DOM 元素。 对于这两种情况, React 提供了一种应急方案。
ref 回调属性
React 支持一个特殊的属性ref,您可以通过它连接到任何组件。ref 带有一个回调函数,并且回调函数在组件挂载或者卸载时将立即执行。
当 ref 属性用在HTML元素上时, ref 回调函数接收一个潜在的DOM元素作为它的参数。 例如, 这段代码用 ref 回调函数存储一个DOM节点的引用:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// 用原生的DOM API明确文本输入框的焦点
this.textInput.focus();
}
render() {
// 用ref回调函数存储一个文本输入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 属性,因为它们没有实例。 然而,你可以这样做, 在功能性组件的render 功能里面使用ref属性:
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>
);
}
不要过度使用 Refs
你的第一意愿可能是用refs在你的应用里实现 ""让事情发生"" 。 如果是这样的话, 花一点时间更仔细的考虑state应该属于组件的那个层级。常常, 很显然,放在合适地方的state 在层次结构中处于一个更高的层次。 看这个 Lifting State Up 译文地址例子指南