React - ref

reference 引用

function A (){
    return (<h1>组件AAA</h1>)
}

<A ref="comA" />   // 不可这样使用,但是函数组件内部是可以使用ref的

过时方式(不要使用)

以聚焦input事件为例,以前的ref使用方式,ref 值为string已经过时,随时可能被移除(不建议使用,在16版中已不再可用)

export default class RefComp extends React.Component {
  render() {
    return (
      <div>
        <input ref="text" type="text" />
        <button
          onClick={() => {
            console.log(this);
            this.refs.text.focus()
          }}>点击 </button>
      </div>
    );
  }
}

ref值的两种形式

ref 的值根据节点的类型而有所不同:

  • ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。

  • ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。

  • 你不能在函数组件上使用 ref 属性,因为他们没有实例。

1.使用React.createRef() 创建( React 16.3 版本引入)

1.1 html 组件
export default class RefComp extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();    // 创建ref
  }

  render() {
    return (
      <div>
        <input ref={this.myRef} type="type" />
        <button
          onClick={() => {
            this.myRef.current.focus();    // 访问 ref
          }}
        >
          点击
        </button>
      </div>
    );
  }
}

// react 会在组建挂载是给this.myRef的current属性出入Dom元素,并在组件卸载时传入null值。
// ref 会在componentDidMount 和 componentDidUpdate 生命周期钩子触发前更新
1.2 自定义组件(类组件)
class Button extends React.Component {
  render() {
    return <input type="发type" ref={this.props.refs} />;
  }
}

export default class RefComp extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  render() {
    return (
      <div>
        <Button refs={this.myRef} />  // 注意不要使用ref 传值,会报错
        <button
          onClick={() => {
            this.myRef.current.focus();
          }}
        >
          点击
        </button>
      </div>
    );
  }
}

由于通过React.createRef() 创建的是一个对象,ref等于这个对象,其实是个对象的content赋值,突发奇想,如果自定义一个对象并给他添加属性content:null,是否可以作用相同,测试结果为yes.

export default class RefComp extends React.Component {
  constructor(props) {
    super(props);
    // this.myRef = React.createRef();
    this.myRef = {
      content: null
    };
  }

  render() {
    return (
      <div>
        <input type="type" ref={this.myRef} />
        <button
          onClick={() => {
            this.myRef.current.focus();
          }}
        >
          点击
        </button>
      </div>
    );
  }
}
1.3 自定义组件(函数组件)
function Button() {
  return <input type="type" refs={this.props.ref} />;
}

export default class RefComp extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }

  render() {
    return (
      <div>
        <Button type="type" refs={this.myRef} />
        <button
          onClick={() => {
            this.myRef.current.focus();
          }}
        >
          点击
        </button>
      </div>
    );
  }
}

在这里插入图片描述

但函数组建内部是可以正常使用ref的

function Button() {
   const myRef = React.createRef();
  return <input type="type" refs={myRef} />;
}

2.使用函数 - 回调 Refs

export default class RefComp extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = null;
  }
  handleRef = el => {
    this.myRef = el;
  };
  render() {
    return (
      <div>
        <input type="type" ref={this.handleRef} />
		/**
		 <input type="type" ref={el=>{this.myRef = el}} />
		 如果这边是这么写的话,会导致componentDidMount 和 componentDidUpdate时候,都会重新计算ref
		*/

        <button
          onClick={() => {
            this.myRef.focus();
          }}
        >
          点击
        </button>
      </div>
    );
  }
}

其他使用和React.createRef() 相同

何时使用 Refs

直接操作dom元素中的某一个方法,或者使用自定义组件中的某一个方法

下面是几个适合使用 refs 的情况:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。

避免使用 refs 来做任何可以通过声明式实现来完成的事情。

举个例子,避免在 Dialog 组件里暴露 open()close() 方法,最好传递 isOpen 属性。

ref 转发

function A(props, ref) {
  return <h1 ref={ref}>{props.words}</h1>;
}

const NewA = React.forwardRef(A);

export default class RefComp extends React.Component {
  myRef = React.createRef();

  componentDidMount() {
    console.log(this.myRef.current);
  }
  render() {
    return <NewA ref={this.myRef} words="hello" />;
  }
}

通过上例,解释ref转发,是指将ref指向组件内部某个组件(元素组件或者类组件)

React.forwardRef() 参数:函数组件(不能是类组件),该函数组件的第二个参数为传入的ref对象

​ 返回:新的组件

如果我想给一个类组件左ref转发,有什么好的方法呢?

class A extends React.Component {
  render() {
    return <h1 ref={this.props.ref1}>{this.props.words}</h1>;
  }
}

export default class RefComp extends React.Component {
  myRef = React.createRef();

  componentDidMount() {
    console.log(this.myRef.current);
  }
  render() {
    return <A ref1={this.myRef} words="hello" />;
  }
}

只能使用props参数传入的方式

发布了45 篇原创文章 · 获赞 14 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/cmchenmei/article/details/103992332