Refs and the DOM
在标准的React数据流中,props
是在父组件和其子组件中唯一的交流手段。为了修改一个子,你需要通过新的props
重新渲染。然而,在很小一部分情况下,需要强制修改标准数据流外部的一些数据。子组件需要被修改成一个立即React元素,或者一个DOM元素,React为这两种情况提供了一个问题解决方案。
The ref Callback Attribute
React支持一个可以供任何组件使用的特殊的属性。ref
属性接收一个回调函数,然后这个回调函数会在组件被挂载或者卸载的时候立即执行。
当ref
属性使用在HTML元素中的时候,ref
回调函数接收下层DOM元素作为其参数:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
//
focus() {
this.textInput.focus();
}
render() {
return (
<div>
//这个ref函数的回调函数参数为当前DOM元素
//ref回调函数存储了一个text input DOM element的引用在this.textInput里面
<input type="text" ref={(input) => this.textInput = input} />
<input type="button" value="Focus the text input" onClick={this.focus} />
</div>
);
}
}
React在挂载组件的时候会以Input DOM element
为参数调用ref
回调函数,并且在卸载组件的时候以null
为参数调用这个回调函数。
使用ref
回调函数来在class中设置一个属性是很平常的模式,如果你现在使用this.refs.myRefName
来访问refs,建议使用这种方法来进行替代。
当ref
属性用在自定义组件上的时候,ref
回调函数接收立即挂载的组件作为其参数:
//当你需要挂载之后立即进行一次模拟
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput
ref={(input) => this.textInput = input} />
);
}
}
你可能不需要再函数式组件中使用ref
属性,因为其根本没有进行实例化,然而你可以使用ref
属性在render
函数内部:
function CustomTextInput(props) {
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更加清晰,