0204refs详解-组件-React

1 概述

组件内的标签通过定义ref属性来标识自己。

做一个小实例,如下图所示:

在这里插入图片描述

两个输入框,第一个输入框输入内容,点击后面按钮,弹窗显示输入内容;第二输入框,失去焦点弹窗显示输入内容。

这里我需要获取页面DOM input,进而获取输入框内容,下面我来看看在react怎么怎么做。

1 字符串形式refs

示例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>0801_字符串形式refs</title>
</head>

<body>
  <div id="test1"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    // 1.创建组件
    class Person extends React.Component {
           render() {
        return (
          <div>
            <input ref="input1" type="text" placeholder="点击按钮提示数据"/>
            <button onClick={this.showData}>点击显示数据</button><br/>
            <input ref="input2" type="text" placeholder="失去焦点提示数据" onBlur={this.showData1}/>
          </div>
        )
      }
      // 点击提示数据
      showData = () => {
        let {input1} = this.refs
        alert(input1.value)
      }

      // 失去焦点提示数据
      showData1 = () => {
        let {input2} = this.refs
        alert(input2.value)
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Person/>, document.getElementById('test1'))
    
  </script>
</body>

</html>

字符串形式refs格式:

// refs 声明
<标签 ref="xxx" />
// refs 使用
this.refs.xxx

this.refs.xxx表示的不是虚拟DO M,而是虚拟DOM转化后的真实DOM。

2 回调形式refs

2.1 基本使用

上述字符串形式refs官网不建议使用,它存在一些问题,比如效率问题等,在后续更新中可能废弃。

react还提供一种回调形式的refs,以上面实例为例,使用回调形式ref,代码如下所示:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>0802_回调形式refs</title>
</head>

<body>
  <div id="test1"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    // 1.创建组件
    class Person extends React.Component {
      // 对标签属性类型、必要性做限制
     
      render() {
        return (
          <div>
            <input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据"/>
            <button onClick={this.showData}>点击显示数据</button><br/>
            <input ref={c => this.input2 = c} type="text" placeholder="失去焦点提示数据" onBlur={this.showData1}/>
          </div>
        )
      }
      // 点击提示数据
      showData = () => {
        let {input1} = this
        alert(input1.value)
      }

      // 失去焦点提示数据
      showData1 = () => {
        let {input2} = this
        alert(input2.value)
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Person/>, document.getElementById('test1'))
    
  </script>
</body>

</html>

回调形式ref格式:

ref={结点参数 => {this.xxx=结点参数}} // 把传递的参数结点挂载在组件实例上

2.2 回调refs调用次数问题

官网说明:

If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the ref callback as a bound method on the class, but note that it shouldn’t matter in most cases.

如果回调函数以内联函数定义,在更新的时候会被调用2次,第一次传递的结点为null,第二次才传递DOM元素。因为每次render都会创建新的函数实例,react需要清理旧的ref,设置新的ref。如果要使用回调形式ref,需要把ref回调定义在组件实例上。

示例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>0803_回调refs执行次数问题</title>
</head>

<body>
  <div id="test1"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    // 1.创建组件
    class Person extends React.Component {
      // 对标签属性类型、必要性做限制
      state = {
        isHot: true
      }
      render() {
        return (
          <div>
            <h2>今天天气很{this.state.isHot?'炎热': '凉爽'}</h2>
            <button onClick={this.changeWeather}>切换天气</button><br/>
            {/*<input ref={(c) => {this.input1 = c;console.log('@', c);}} type="text" placeholder="点击按钮提示数据"/>*/}
            <input ref={this.saveInput} type="text" placeholder="点击按钮提示数据"/>
            <button onClick={this.showData}>点击显示数据</button><br/>
          </div>
        )
      }
      // 点击提示数据
      showData = () => {
        let {input1} = this
        alert(input1.value)
      }
      // 回调input ref
      saveInput = c => {
        this.Input1 = c
      }

      changeWeather = () => {
        let {isHot} = this.state
        this.setState({isHot: !isHot})
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Person/>, document.getElementById('test1'))
    
  </script>
</body>

</html>

3 API形式refs

AP I格式上目前React官方推荐的方式,通用格式:

Class xxx extends React.Component{
	xxx = React.createRef()
  return {
    <标签 ref={this.xxx} />
  }
}

还是以最开始实例为例,代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>0801_字符串形式refs</title>
</head>

<body>
  <div id="test1"></div>
  <!-- react核心库 -->
  <script type="text/javascript" src="../js/react.development.js"></script>
  <!-- 用于支持react操作DOM -->
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <!-- 用于将jsx转为js -->
  <script type="text/javascript" src="../js/babel.min.js"></script>

  <script type="text/babel">

    // 1.创建组件
    class Person extends React.Component {
      /*
         React.createRef()调用后返回容器,存放被ref标识的结点;该容器只能存放一个结点,后放入覆盖之前。
       */
      myRef1 = React.createRef()
      myRef2 = React.createRef()
      render() {

        return (
          <div>
            <input ref={this.myRef1} type="text" placeholder="点击按钮提示数据" />
            {/*<button ref={this.myRef1} onClick={this.showData}>点击显示数据</button><br/>*/}
            <button onClick={this.showData}>点击显示数据</button><br />
            <input ref={this.myRef2} type="text" placeholder="失去焦点提示数据" onBlur={this.showData1} />
          </div>
        )
      }
      // 点击提示数据
      showData = () => {
        alert(this.myRef1.current.value)
      }

      // 失去焦点提示数据
      showData1 = () => {
        alert(this.myRef2.current.value)
      }
    }

    // 2.渲染虚拟DOM到页面
    ReactDOM.render(<Person />, document.getElementById('test1'))

  </script>
</body>

</html>

说明:

  • APi创建的ref一一对应,即一个结点对应一个ref;如果多个元素使用相同的ref,最后一个覆盖前面的。

4 几种ref形式对比

  • 字符串形式ref,定义使用形式简单,方便;但是官网不建议使用,虽然使用大多数情况下并不会有什么影响。
  • 回调形式ref,定义和使用相对麻烦。
  • API方式ref,每个元素都需要新创建一个ref,官网建议方式。

后记

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/react-study

参考:

[1]尚硅谷React教程(2022加更,B站超火react教程)[CP/OL].2020-12-15.p27-p31.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值