React Refs用法

快来打我* 2022-05-26 04:59 331阅读 0赞

Refs介绍


Refs提供了一种访问在render方法中创建的DOM节点或者React元素的方法。在典型的数据流中,props是父子组件交互的唯一方式,想要修改子组件,需要使用新的pros重新渲染它。凡事有例外,某些情况下我们需要在典型数据流外,强制修改子代,这个时候可以使用Refs。

下面我将通过例子的方式详细介绍如何设置Refs以及如何访问Refs

Refs设置


设置Refs有两种方式:

  1. Callback Refs,通过这种方式,我们可以更细致的控制Refs的设置和置空;
  2. 使用React.createRef()方法。

下面,我通过代码展示的形式,分别介绍如何设置Refs

Callback Refs

ref属性接受一个回调函数,它在组件被加载或者卸载时会立即执行,当给HTML元素添加ref属性的时候,Refs回调接受了底层的Dom元素作为参数,当组件卸载时,Refs回调会接受null作为参数。回调函数会在componentDidMount或者componentDidUpdate这些生命周期之前回调之前执行。
实例如下:

  1. //CustomTextInput.js
  2. class CustomTextInput extends Component{
  3. constructor(props){
  4. super(props);
  5. this.textInput = null;
  6. this.focus = this.focus.bind(this);
  7. }
  8. focus(){
  9. if(this.textInput){
  10. this.textInput.focus();
  11. }
  12. }
  13. render(){
  14. return(
  15. <div>
  16. <input type="text" ref = {(input) => {
  17. this.textInput = input}}/>
  18. <input type="button" value = "Focus the text input" onClick={
  19. this.focus}/>
  20. </div>
  21. )
  22. }
  23. }

注意:如果ref回调以内联函数的方式定义,在更新期间,它会被调用两次,第一次参数是null,之后参数是DOM元素,这是因为每次渲染中都会创建一个新的函数实例。因此,React需要清理旧的ref,然后设置成新的。通过将Refs回调定义成类的绑定函数的形式可以解决这个问题,不过通常情况下无关紧要。

React.createRef

ref属性用于class声明的自定义组件时,ref接受的是已经加载的组件实例,这种方法只对class声明的组件有效,我们不能在函数式组件上使用ref,因为它们没有实例,但我们可以在函数式组件内部使用ref

下面的例子,我通过使用React.createRef()方法为一个类组件添加ref

  1. //AutoFocusTextInput.js
  2. import { CustomTextInput } from "./CustomTextInput"
  3. class AutoFocusTextInput extends Component{
  4. constructor(props){
  5. super(props);
  6. this.textInput = React.createRef()
  7. }
  8. componentDidMount(){
  9. this.textInput.current.textInput.focus();
  10. }
  11. render(){
  12. return(
  13. <CustomTextInput ref = {
  14. this.textInput}/>
  15. )
  16. }
  17. }
  18. export default AutoFocusTextInput;

访问Refs


ref的值取决于节点的类型:当ref属性被用于一个普通的HTML元素时,创建Refs时将接受底层的Dom元素作为它的current属性来创建,当ref属性被用于一个自定义组件的时候,创建Refs时将接受自定义组件的实例作为它的current

从上面可以得知,可以使用ref中的current属性对节点的引用进行访问,比如说:

  1. const node = this.myRef.current

Refs传递问题


关于Refs,有一点需要注意:refprops具有一个不同之处:ref是不能像props那样传递的,refkey类似,都是直被React操作。如果我们把给高阶组件生成的组件添加ref,那么这个ref指向的是高阶组件新的容器组件,而不是被包裹的组件。React为我们提供了一种解决方法:
Ref forwarding可以把一个组件的ref传递给它的子组件,对高阶组件很有用。React.forwardRef接受一个render函数作为参数,返回一个组件实例。render函数接收propsref作为参数,返回一个React节点。
下面我将对上一篇文章React Context和高阶组件HOC用法中的高阶组件,实现把ref传递给被包裹的组件。代码如下:

  1. export function WithTheme(Component) {
  2. class WithThemeComponent extends Component{
  3. render(){
  4. const { forwardedRef ,...rest } = this.props;
  5. return(
  6. <ThemeContext.Consumer>
  7. {theme => <Component {...rest} theme = {theme} ref = {forwardedRef}/>}
  8. </ThemeContext.Consumer>
  9. )
  10. }
  11. }
  12. function forwardRef(props,ref){
  13. return <WithThemeComponent {...props} forwardedRef = {ref}/>
  14. }
  15. return React.forwardRef(forwardRef);
  16. }

注意


如果可以使用声明式实现,那么就尽量避免使用Refs。例如:当设计一个Dialog组件的时候,不要直接暴露open和close方法,最好传递isOpen属性。牢记声明式React的一大优点。

发表评论

表情:
评论列表 (有 0 条评论,331人围观)

还没有评论,来说两句吧...

相关阅读

    相关 reactref

    ref 的由来 在典型的 React 数据流中,props 是父组件与子组件交互的唯一方式。要修改一个子组件,你需要使用新的 props 来重新渲染它。但是,在某些情况下

    相关 react------refs

    refs:组件内的标签都可以定义ref属性来标识自己        在组件中科院通过this.refs.refName来获取对应的真实DOM对象        用于操作指定

    相关 oracle中REF Cursor

    1,什么是 REF游标 ?  动态关联结果集的临时对象。即在运行的时候动态决定执行查询。   2,REF 游标 有什么作用?  实现在程序间传递结果集的功能,利

    相关 实例属性ref

    一 点睛 1 直接通过对象.的方式调用的属性,是来自于data或computed中的属性,但 vue 对象中的 el、data 等等这些键也称为属性,这些属性就是 Vue