React 中的 Refs(9)

Refs

允許我們訪問真實 DOM

一般的,React 數(shù)據(jù)流是通過 props 來實現(xiàn)父子組件的交互

Refs 允許我們用于強(qiáng)制修改子組件

// 輸入框焦點
class MyInput extends React.Component {
  constructor(props) {
    super(props);

    this.inputRef = React.createRef();
  }

  inputOperating() {
    console.log(this.inputRef.current.value);
    this.inputRef.current.focus();
  }

  render() {
    return (
      <div>
        <input type="text" ref={this.inputRef} />
        <button onClick={this.inputOperating.bind(this)}>獲取焦點</button>
      </div>
    );
  }
}

// 媒體管理
class MyVideo extends React.Component {
  constructor() {
    super();
    this.vdoRefs = React.createRef();
  }

  vdoPause() {
    this.vdoRefs.current.pause();
  }
  vdoPlay() {
    this.vdoRefs.current.play();
  }

  render() {
    return (
      <div>
        <video
          ref={this.vdoRefs}
          src="http://vjs.zencdn.net/v/oceans.mp4"
          controls
          autoPlay
          muted
        ></video>
        <button onClick={this.vdoPause.bind(this)}>暫停</button>
        <button onClick={this.vdoPlay.bind(this)}>播放</button>
      </div>
    );
  }
}
// 操作動畫
class MyBox extends React.Component {
  constructor(props) {
    super(props);
    this.boxRef = React.createRef();
  }
  boxExtend() {
    const oBox = this.boxRef.current;
    oBox.style.width = "500px";
    oBox.style.height = "500px";
  }
  render() {
    return (
      <>
        <div
          ref={this.boxRef}
          style={{
            width: 200 + "px",
            height: 200 + "px",
            backgroundColor: "orange",
            transition: "all 1s",
          }}
        ></div>
        <button onClick={this.boxExtend.bind(this)}>Extend</button>
      </>
    );
  }
}

createRef 用法細(xì)節(jié)

  • 通過 createRef 創(chuàng)建 ref 對象
  • 通過元素的 ref 屬性可以附加到 React 元素上
  • 一般通過構(gòu)造器中給 this 賦值一個 ref,方便整個組件使用
  • ref 只要傳遞 React 元素中,就可以利用 refcurrent 屬性訪問到該真實 DOM 節(jié)點
  • ref 在 componentDidMountcomponentDidUpdate 觸發(fā)前更新

ref 不同的使用方式:

  • ref 放在 HTML 元素上,則指向真實 DOM 節(jié)點
  • ref 放在 class 組件上,則指向組件實例
    <MyBox ref={xxx}/>
  • ref 放在函數(shù)組件上,不能增加 ref 屬性,可以使用 React.useRef()

forwardRef (v16.3 以上版本)

將子組件的 ref 暴露給父組件

React.forwardRef((props, ref) => { return React 元素})
const MyInput = React.forwardRef((props, ref) => (
  // ref 參數(shù)只能在,用 forwardRef 定義的組件內(nèi)可接收
  <input type="text" placeholder={props.placeholder} ref={ref} />
));

class App extends React.Component {
  constructor(props) {
    super(props);
    this.myInputRef = React.createRef();
  }
  inputOperate() {
    this.myInputRef.current.value = "";
    this.myInputRef.current.focus();
  }
  render() {
    return (
      <div>
        <MyInput placeholder="請輸入" ref={this.myInputRef} />
        <button onClick={this.inputOperate.bind(this)}>獲取焦點</button>
        {/* <MyVideo /> */}
        {/* <MyBox ref={xxx}/> */}
      </div>
    );
  }
}
// 高階組件 ref 轉(zhuǎn)發(fā)
class MyInput extends React.Component {
  render() {
    return <input type="text" placeholder={this.props.placeholder} />;
  }
}

function InputHoc(WarpperComponent) {
  class Input extends React.Component {
    render() {
      const { forwardRef, ...props } = this.props;
      return <WarpperComponent ref={forwardRef} {...props} />;
    }
  }
  function forwardRef(props, ref) {
    return <Input forwardRef={ref} {...props} />;
  }

  // 設(shè)置別名
  forwardRef.displayName = `Input - ${WarpperComponent.name}`;
  return React.forwardRef(forwardRef);


  // return React.forwardRef((props, ref) => (
  //   <Input forwardRef={ref} {...props} />
  // ));
}

const MyInputHoc = InputHoc(MyInput);

class App extends React.Component {
  constructor(props) {
    super(props);

    this.myInputRef = React.createRef();
  }

  componentDidMount() {
    console.log(this.myInputRef);
  }

  inputOperate() {
    this.myInputRef.current.value = "";
    this.myInputRef.current.focus();
  }

  render() {
    return (
      <>
        <MyInputHoc ref={this.myInputRef} placeholder="請輸入" />
        <button onClick={this.inputOperate.bind(this)}>獲取焦點</button>
      </>
    );
  }
}

Refs 轉(zhuǎn)發(fā)(v16.2 及以下)

  1. 通過 props 轉(zhuǎn)發(fā)
class MyInput extends React.Component {
  render() {
    return <input type="text" ref={this.props.inputRef} />;
  }
}

// 通過 props 轉(zhuǎn)發(fā)
class App extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }
  componentDidMount() {
    console.log(this.inputRef);
  }

  render() {
    return (
      <div>
        <MyInput inputRef={this.inputRef} />
      </div>
    );
  }
}
  1. 回調(diào) Refs
class App extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = null;
  }
  setMyInput(el) {
    this.inputRef = el;
  }
  focusInput() {
    this.inputRef.value = "";
    this.inputRef.focus();
  }
  render() {
    return (
      <div>
        <input type="text" ref={this.setMyInput.bind(this)} />
        <button onClick={this.focusInput.bind(this)}>click</button>
      </div>
    );
  }
}
  1. 字符串 refs(不建議使用)
  • 組件實例下面的 refs 集合里的 ref
  • 需要 React 保持跟蹤當(dāng)前正在渲染的組件,this 沒法確定
  • React 獲取 ref 可能會比較慢
  • 不能在 render 中工作
  • 不能組合,只能設(shè)置一個 ref
class App extends React.Component {
  componentDidMount() {
    // 字符串 refs
    console.log(this.refs.inputRef);
  }

  render() {
    console.log(this.refs.inputRef); // undefined
    return (
      <div>
        <input type='text' ref='inputRef' />
      </div>
    );
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Ref 轉(zhuǎn)發(fā)是一項將 ref[https://react.docschina.org/docs/refs-and-...
    不再猶豫_c61b閱讀 543評論 0 0
  • 歡迎訪問主頁,有更多文章內(nèi)容轉(zhuǎn)載請注明原出處原文鏈接地址:React中Refs的使用方法 什么是Refs Refs...
    Vincent_cy閱讀 2,532評論 0 2
  • 在經(jīng)典的 React 數(shù)據(jù)流中,props 是父組件與子組件交互的唯一方式,而且 props 是自上而下(由父及子...
    越前君閱讀 1,282評論 0 5
  • 以前的字符串式refs(this.refs.xxx)已被遺棄,這里整理的都是最新版本的用法 前言: 先說下Reac...
    南山碼僧閱讀 2,261評論 0 1
  • Refs提供了一個訪問render()方法內(nèi)DOM節(jié)點或者ReactNode的方法 典型的React數(shù)據(jù)流中,pr...
    Waitingforyu閱讀 1,186評論 0 0

友情鏈接更多精彩內(nèi)容