在进行React开发时,有时在组件的代码中需要访问实际的Dom对象,这个时候就要用到ref这个属性来将 dom对象的值保存进来,以便代码访问。
一、Create Ref
自从 React v16.3开始,在类组件中推荐使用React.createRef()创建Refs,通过ref附加到组件中,对该节点的引用通过ref的current属性访问
React在组件挂载时给current传入DOM元素,并在组件卸载时传入null,ref会在生命周期函数前更新完成
代码举例:
import React, { Component, createRef} from "react";
class App extends Component {
constructor(props) {
super(props);
this.h1Ref = createRef();
}
componentDidMount() {
console.log("React.createRef()");
console.log(this.h1Ref.current);
}
render() {
return <h1 ref={this.h1Ref}>Hello World!</h1>;
}
}
export default App;
二、useRef
当在函数组件中使用React.createRef()会抛出以下错误:
Uncaught Invariant Violation: Function components cannot have refs. Did you mean to use React.forwardRef()?
原因:函数组件和class组件根本区别是,函数组件没有实例,所以无法使用实例对象,取而代之的为useRef,或使用forwardRef
作用:
获取DOM节点
获取组件实例
渲染周期之间共享数据存储(state修改会触发重新渲染,所以不能跨周期共享)
使用方法:与createRef类似,挂在current上
import React, { useEffect, useRef } from 'react';
function App() {
const h1Ref = useRef();
useEffect(() => {
console.log('useRef')
console.log(h1Ref.current)
}, [])
return <h1 ref={h1Ref}>Hello World!</h1>
}
export default App;
三、Ref 转发,用于引用子组件中的Dom元素
有时候需要引用子组件中的Dom对象,就需要传递ref给子组件,需要用到React.forwardRef函数,常规函数组件和 class 组件不接收 ref 参数,且 props 中也不存在 ref。以下这个例子展示了,将ref转发到了最终的button标签上,其实Ref 转发不仅限于 DOM 组件,你也可以转发 refs到 class组件实例中。
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// 你可以直接获取 DOM button 的 ref:
const ref = React.createRef();
// 此时的ref即React.forwardRef的参数之一
<FancyButton ref={ref}>Click me!</FancyButton>;
四、Callback Ref
在旧版本中,Callback Ref能助你更精细地控制何时 refs
被设置和解除,传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数。
React 将在组件挂载时,会调用 ref 回调函数并传入 DOM 元素,当卸载时调用它并传入 null。在 componentDidMount 或 componentDidUpdate 触发前,React 会保证 refs 一定是最新的。
使用方式:ref={element => (this.eleref = element)}
获取DOM元素节点:
import React, { Component } from "react";
class App extends Component {
componentDidMount() {
console.log("Callback Ref");
console.log(this.h1Ref);
}
render() {
return (
<div>
<h1 ref={element => (this.h1Ref = element)}>Hello World!</h1>
</div>
);
}
}
export default App;
// 打印结果
Callback Ref
<h1>Hello World!</h1>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)