React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > React Refs and the DOM

React高级指引之Refs and the DOM使用时机详解

作者:码农小菲

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

Refs and the DOM

何时使用 Refs

勿过度使用 Refs

创建 Refs

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

访问 Refs

在 ref 的 current 属性中被访问

const node = this.myRef.current;

为 DOM 元素添加 ref

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // 创建一个 ref 来存储 textInput 的 DOM 元素
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }
  focusTextInput() {
    // 直接使用原生 API 使 text 输入框获得焦点
    // 注意:我们通过 "current" 来访问 DOM 节点
    this.textInput.current.focus();
  }
  render() {
    // 告诉 React 我们想把 <input> ref 关联到
    // 构造器里创建的 `textInput` 上
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

为 class 组件添加 Ref

  class AutoFocusTextInput extends React.Component {
    constructor(props) {
      super(props);
      this.textInput = React.createRef();
    }
    componentDidMount() {
      this.textInput.current.focusTextInput();
    }
    render() {
      return (
        <CustomTextInput ref={this.textInput} />
      );
    }
  }

不能在函数组件上使用 ref 属性,如果要在函数组件中使用 ref,你可以使用 forwardRef(可与 useImperativeHandle 结合使用),或者可以将该组件转化为 class 组件

function CustomTextInput(props) {
   // 这里必须声明 textInput,这样 ref 才可以引用它
   const textInput = useRef(null);
   function handleClick() {
     textInput.current.focus();
   }
   return (
     <div>
       <input
         type="text"
         ref={textInput} />
       <input
         type="button"
         value="Focus the text input"
         onClick={handleClick}
       />
     </div>
   );
 }

将 DOM Refs 暴露给父组件

不建议暴露 DOM 节点

回调 Refs

    class CustomTextInput extends React.Component {
     constructor(props) {
       super(props);
       this.textInput = null;
       this.setTextInputRef = element => {
         this.textInput = element;
       };
       this.focusTextInput = () => {
         // 使用原生 DOM API 使 text 输入框获得焦点
         if (this.textInput) this.textInput.focus();
       };
     }
     componentDidMount() {
       // 组件挂载后,让文本框自动获得焦点
       this.focusTextInput();
     }
     render() {
       // 使用 `ref` 的回调函数将 text 输入框 DOM 节点的引用存储到 React
       // 实例上(比如 this.textInput)
       return (
         <div>
           <input
             type="text"
             ref={this.setTextInputRef}
           />
           <input
             type="button"
             value="Focus the text input"
             onClick={this.focusTextInput}
           />
         </div>
       );
     }
   }
// 在上面的例子中,Parent 把它的 refs 回调函数当作 inputRef props 传递给了 CustomTextInput,而且 CustomTextInput 把相同的函数作为特殊的 ref 属性传递给了 <input>。结果是,在 Parent 中的 this.inputElement 会被设置为与 CustomTextInput 中的 input 元素相对应的 DOM 节点

如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。

到此这篇关于React高级指引之Refs and the DOM使用时机详解的文章就介绍到这了,更多相关React Refs and the DOM内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文