美文网首页
React 中的 Refs(9)

React 中的 Refs(9)

作者: 示十 | 来源:发表于2022-10-07 08:58 被阅读0次

    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.haomeiwen.com/subject/dqunortx.html