react-复习(4)受控组件非受控组件和ref的使用

React的受控组件与非受控组件的概念是相对于表单而言,如果一个 input 表单元素的值是由 React 控制,就其称为受控组件。非受控组件就像是运行在 React 体系之外的表单元素,当用户将数据输入到表单字段(例如 input,dropdown 等)时,React 不需要做任何事情就可以映射更新后的信息。然而,这也意味着,你无法强制给这个表单字段设置一个特定值。

受控组件

比如我们常用利用onChange事件保存用户输入的信息,就是一个受控组件:

constructor() {
    super();
    this.state = {
      value: "",
    };
  }
  render() {
    const { value } = this.state;
    return (
      <div>
        <input
          value={value}
          onChange={(e) => this.setState({ value: e.target.value })}
        />
      </div>
    );
  }

非受控组件

但是当使用input上传一个或多个文件时呢,因为它的值只能由用户设置,而不能通过代码控制。所以只能使用非受控组件。

ref的使用

创建非受控组件,我们一般借助ref。使用ref,有三种不同的方式。

1:使用字符串

我们将上面的代码改造一下:

render() {
    const { value } = this.state;
    return (
      <div>
        <p>{value}</p>
        <input ref="input" />
        <button onClick={this.btnClick}>获取input框中value的值</button>
      </div>
    );
  }
  btnClick = () => {
    this.setState({
      value: this.refs.input.value,
    });
  };

输入数值,点击按钮,就能看到value值已经被我们获取到了。


由于设置的是字符串,每一次执行渲染时都会重新赋一次值,可能会发生内存泄露的隐患,因此控制台中会出现警告,官方不建议使用字符串的方式创建ref

2:使用回调函数的方式

使用回调函数创建ref,回调函数中的参数就是使用ref的元素。我们把这个参数保存一下,就可以使用ref了。这种方法不会出现警告,在第三种方法出现之前,常用这种方式创建。

render() {
    const { value } = this.state;
    return (
      <div>
        <p>{value}</p>
        <input ref={(input) => this.input = input} />
        <button onClick={this.btnClick}>获取input框中value的值</button>
      </div>
    );
  }
  btnClick = () => {
    this.setState({
      value: this.input.value,
    });
  };

3:使用createRefAPI

使用React.createRef()创建一个ref,生成一个对象,将使用到ref的元素放在current属性中

constructor() {
    super();
    this.state = {
      value: "",
    };
    this.input = React.createRef();
  }
  render() {
    const { value } = this.state;
    return (
      <div>
        <p>{value}</p>
        <input ref={this.input} />
        <button onClick={this.btnClick}>获取input框中value的值</button>
      </div>
    );
  }
  btnClick = () => {
    this.setState({
      value: this.input.current.value,
    });
  };

注意,取到值需要this.input.current.value,较比第二种方法,多了一个.current
当然了,如果使用hooks,还有另一种方法,useRef,由于是复习篇幅,hooks会在后续篇幅中呈现。

ref的转发

如果使用ref,在父组件中想要获取子组件的元素怎么办呢?

这个时候就需要用到forwardRefAPI了,它接收两个参数,一个是props值,一个是声明好的ref。较比于函数式组件,多了第二个参数。
我们现在父组件中创建好ref,并传给子组件

export default class App extends React.Component {
  constructor() {
    super();
    this.input = React.createRef();
  }
  render() {
    return (
      <div>
        <Modal ref={this.input} />
        <button onClick={this.btnClick}>显示value值</button>
      </div>
    );
  }
  btnClick = () => {
    console.log('this.input.current.value :>> ', this.input.current.value);
  }
}

接下来在组件中使用forwardRef创建一个函数式组件,将ref转发给需要用的的元素节点就行啦。

export default React.forwardRef((props, ref) => {
  class Modal extends React.Component {
    render() {
      return (
        <div>
          <input ref={ref} defaultValue="11"></input>
        </div>
      );
    }
  }
  return <Modal />;
});

上面代码中我们返回了一个class的组件,当然你也可以直接写成函数式组件的形式。如果想要获取整个子组件,不用forwardRef进行包裹就可以了。

结语

上面父组件获取子组件input输入框的值显然不止这一种方法,也可以在父组件中定义好state,写好改变state的方法传递给子组件,这样也能拿到子组件元素中的值。那么合适适合使用ref呢?官网已经给出了答案:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。

同样,不好的地方官方也进行了说明:

由于笔者还是个前端小萌新,难免会有纰漏错误,欢迎大佬们进行指点!

参考文献

React官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值