React 中的 Refs(9)

Refs

允许我们访问真实 DOM

一般的,React 数据流是通过 props 来实现父子组件的交互

Refs 允许我们用于强制修改子组件

// 输入框焦点
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 用法细节

  • 通过 createRef 创建 ref 对象
  • 通过元素的 ref 属性可以附加到 React 元素上
  • 一般通过构造器中给 this 赋值一个 ref,方便整个组件使用
  • ref 只要传递 React 元素中,就可以利用 refcurrent 属性访问到该真实 DOM 节点
  • 「ref 在 componentDidMountcomponentDidUpdate 触发前更新」

ref 不同的使用方式:

  • ref 放在 HTML 元素上,则指向真实 DOM 节点
  • ref 放在 class 组件上,则指向组件实例<MyBox ref={xxx}/>
  • ref 放在函数组件上,不能增加 ref 属性,可以使用 React.useRef()

forwardRef (v16.3 以上版本)

将子组件的 ref 暴露给父组件

React.forwardRef((props, ref) => { return React 元素})
const MyInput = React.forwardRef((props, ref) => (
  // ref 参数只能在,用 forwardRef 定义的组件内可接收
  <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 转发
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} />;
  }

  // 设置别名
  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 转发(v16.2 及以下)

  1. 通过 props 转发
class MyInput extends React.Component {
  render() {
    return <input type="text" ref={this.props.inputRef} />;
  }
}

// 通过 props 转发
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. 回调 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 保持跟踪当前正在渲染的组件,this 没法确定
  • React 获取 ref 可能会比较慢
  • 不能在 render 中工作
  • 不能组合,只能设置一个 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>

    );
  }
}


原文始发于微信公众号(前端华先生):React 中的 Refs(9)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/55337.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!