Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
在典型的 React 数据流中,props 是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的 props 来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。对于这两种情况,React 都提供了解决办法。
创建 Refs
Refs 是使用 React.createRef()
创建的,并通过 ref
属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。
我们需要再提交的时候,获取input输入框的值,所以需要获取目标的dom元素,通过ref可以直接获取到input.
从打印的结果我们可以看到,通过 inputRef.current
可以获取input的DOM元素.
class HelloWorld extends React.Component {
constructor(props) {
super(props);
// 创建ref
this.inputRef = React.createRef();
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e){
// 阻止默认提交行为
e.preventDefault();
// 打印ref观察结果
console.log(this.inputRef)
}
render(){
return (
<div>
<form action="/abc" onSubmit={this.handleSubmit}>
<input type="text" ref={this.inputRef}/>
<input type="submit" value="提交" />
</form>
</div>
)
}
}
// 通过调用React自身方法render可以得到当前组件的实例对象,并渲染到页面容器.
ReactDOM.render(<HelloWorld />,document.getElementById('root'));
访问 Refs
当 ref 被传递给 render
中的元素时,对该节点的引用可以在 ref 的 current
属性中被访问。
const node = this.myRef.current;
ref 的值根据节点的类型而有所不同:
- 当
ref
属性用于 HTML 元素时,构造函数中使用React.createRef()
创建的ref
接收底层 DOM 元素作为其current
属性。 - 当
ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其current
属性。 - 你不能在函数组件上使用
ref
属性,因为他们没有实例。在class上声明ref
- 当
ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其current
属性。
- 当
class Demo extends React.Component {
say(){
console.log('this is demo...');
}
render(){
return (
<div>
这是demo
</div>
)
}
}
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
this.demoRef = React.createRef();
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount(){
console.log(this.demoRef.current);
}
handleSubmit(e){
// 阻止默认提交行为
e.preventDefault();
console.log(this.inputRef)
}
render(){
return (
<div>
<Demo ref={this.demoRef}/>
<form action="/abc" onSubmit={this.handleSubmit}>
<input type="text" ref={this.inputRef}/>
<input type="submit" value="提交" />
</form>
</div>
)
}
}
// 通过调用React自身方法render可以得到当前组件的实例对象,并渲染到页面容器.
ReactDOM.render(<HelloWorld />,document.getElementById('root'));
回调 Refs
React 也支持另一种设置 refs 的方式,称为“回调 refs”。它能助你更精细地控制何时 refs 被设置和解除。
不同于传递 createRef()
创建的 ref
属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,以使它们能在其他地方被存储和访问。
下面的例子描述了一个通用的范例:使用 ref
回调函数,在实例的属性中存储对 DOM 节点的引用。
class HelloWorld extends React.Component {
constructor(props) {
super(props);
this.inputRef = null;
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e){
// 阻止默认提交行为
e.preventDefault();
console.log(this.inputRef)
}
render(){
return (
<div>
<form action="/abc" onSubmit={this.handleSubmit}>
<input type="text" ref={el=> this.inputRef = el}/>
<input type="submit" value="提交" />
</form>
</div>
)
}
}
// 通过调用React自身方法render可以得到当前组件的实例对象,并渲染到页面容器.
ReactDOM.render(<HelloWorld />,document.getElementById('root'));
何时使用 Refs
下面是几个适合使用 refs 的情况:
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
避免使用 refs 来做任何可以通过声明式实现来完成的事情。
举个例子,避免在 Dialog
组件里暴露 open()
和 close()
方法,最好传递 isOpen
属性。
- 不要过度使用Refs