某些情况下需要直接修改元素,要修改的子代可以是 React 组件实例,也可以是 DOM 元素。这时就要用到refs来操作DOM。
[注意] 如果可以通过声明式实现,则尽量避免使用 refs。
ref
React 支持给任意组件添加特殊属性ref ,ref可以是一个字符串,也可以是一个属性接受一个回调函数,它在组件被加载或卸载时会立即执行。
[注意]在组件mount
之后再去获取ref
。componentWillMount
和第一次render
时都获取不到,在componentDidMount
才能获取到。
新ref
版本16.3 之前,React 有两种提供 ref
的方式:字符串和回调,因为字符串的方式有些问题,所以官方建议使用回调来使用 ref
。而现在引入的createRef API
,据官方说是一种零缺点的使用ref
的方式,回调方式也可以让让路了。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
然后使用current属性
,即可获得当前元素
this.myRef.current
[注意]使用styledComponents
样式化的元素暴露的接口是innerRef
,而不是ref
<Wrap innerRef={this.itemRef}>
ref传递原理
当给 HTML 元素添加ref 属性
时,ref
回调接收了底层的 DOM 元素作为参数。
React 组件在加载时将 DOM 元素传入 ref 的回调函数,在卸载时则会传入 null。ref 回调会在componentDidMount
或 componentDidUpdate
这些生命周期回调之前执行。
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
this.textInput.focus();
}
render() {
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
更简短的写法如下:
ref={input => this.textInput = input}
类组件
当·ref
属性用于使用 class
声明的自定义组件时,ref
的回调接收的是已经加载的 React 实例。
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focusTextInput();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}
[注意]这种方法仅对 class 声明的 CustomTextInput
有效
函数式组件
不能在函数式组件上使用 ref 属性,因为它们没有实例。
对父组件暴露DOM节点
在子节点上暴露一个特殊的属性。子节点将会获得一个函数属性,并将其作为 ref 属性附加到 DOM 节点。这允许父代通过中间件将 ref 回调给子代的 DOM 节点。
该方法适用于类组件和函数式组件:
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} />
</div>
);
}
class Parent extends React.Component {
render() {
return (
<CustomTextInput
inputRef={el => this.inputElement = el}
/>
);
}
}
在上面的例子中,Parent
将它的 ref
回调作为一个特殊的 inputRef
传递给CustomTextInput
,然后 CustomTextInput
通过ref
属性将其传递给 <input>
。最终,Parent
中的 this.inputElement
将被设置为与 CustomTextInput
中的<input>
元素相对应的 DOM 节点。