Skip to content

ref

绝大部分场景应避免使用 ref,因为它破坏了 React 中以 props 为数据传递介质的典型数据流。

下面介绍下 ref 的常用使用场景

在 DOM 上使用 ref

ref 接受一个回调函数作为值,在组件被挂载或卸载时,回调函数会被调用,在组件被挂载时,回调函数会接受当前 DOM 元素作为参数;组件被卸载时回调函数会接受 null 作为参数

jsx
class AutoFocusTextInput extends Component {
  render() {
    return (
      <div>
        <input type="text" ref={input => (this.textInput = input)} />
      </div>
    );
  }
  componentDidMount() {
    // 通过ref让input自动获取焦点
    this.textInput.focus();
  }
}

AutoFocusTextInput 中为 input 定义 ref,在组件挂载后,通过 ref 获取 input 元素,让其自动获取焦点,否则就很难实现该功能

在组件上使用 ref

例,在使用 AutoFocusTextInput 组件的外部组件 Containter 中控制:

jsx
class AutoFocusTextInput extends Component {
  constructor() {
    super();
  }
  blur = () => {
    this.textInput.blur();
  };
  render() {
    return (
      <div>
        <input type="text" ref={input => (this.textInput = input)} />
      </div>
    );
  }
}

// AutoFocusTextInputContainer.jsx
class AutoFocusTextInputContainer extends Component {
  handleClick = () => {
    // 通过ref调用 组件的方法
    this.inputInstance.blur();
  };
  render() {
    return (
      <div>
        <AutoFocusTextInput ref={(this.inputInstance = input)} />
        <button onClick={this.handleClick}>失去焦点</button>
      </div>
    );
  }
}

通过 ref 获取到了 AutoFocusTextInput 组件的实例对象,并把它赋值给 Container 的 inputInstance 属性,这样就可以通过 inputInstance 调用 AutoFocusTextInput 中的 blur 方法,让已经处于获取焦点状态的 input 失去焦点。

父组件访问子组件的 DOM 节点

某些场景可能会需要。例如父组件需知道这个 DOM 元素的尺寸或位置信息,直接使用 ref 是无法实现的。

这时,可在子组件的 DOM 元素上定义 ref,ref 的值是父组件传递给子组件的一个回调函数,回调函数可以通过一个自定义的属性传递,例如 inputRef, 这样父组件的回调函数中就能获取到这个 DOM 元素

jsx
function Children(props) {
  // 子组件使用父组件传递的inputRef, 为input的ref赋值
  return (
    <div>
      <input ref={props.inputRef} />
    </div>
  );
}

class Parent extends Component {
  render() {
    // 自定义一个属性inputRef,值是一个函数
    return <Children inputRef={el => (this.inputElement = el)} />;
  }
}

从该例中还可发现,即时子组件是函数组件,这种方式同样有效。


共 20 个模块,1301 篇 Markdown 文档。