Bootstrap

React第七节 组件三大属性之 refs 的用法注意事项

1、定义

React 中refs 是允许我们操作DOM 访问组件实例的一种方案。开发人员可以直接使用 refs 访问操作DOM,而不用自身的数据状态,这种方案在实际开发过程中是有必要的,但是不建议通篇使用refs操作DOM,如果是这样,那么我们应该考虑一下,自己设计的组件是否合理,React设计的原理是利用状态和数据驱动UI视图;

2、用途

a、我们想要保存一些数据,但是不想随时更新在视图中;
b、输入框自动聚焦、滚动到某个节点、视频自动播放、图表库(ecahrts)等

3、用法

创建 refs 的方法:
3.1、类式组件中:使用 React.createRefs()
3.2、函数式组件中的 使用 useRefs() Hook
3.3、回调函数形式 在函数式组件、类式组件中均可使用
3.4、字符串形式

a、类式组件通过createRef() 创建 【推荐】

通过createRef() 创建 ref实例,得到的ref实例中会有一个 current 属性,通过current 获取对应的数据;这种方式只适用于类式组件

export default class MyRefs extends Component{
    // 创建 ref
    myTextRef = React.createRef()
    getText = () => {
        console.log('===myTextRef==', this.myTextRef)
        // 获取 input 中的值
        console.log(this.myTextRef.current.value)
        // 获取焦点
        // this.myTextRef.current.focus()
    }

    render() {
        return(
            <>
                <div>
                    <input type="text" ref={this.myTextRef}></input>
                    <button onClick={this.getText}>按钮</button>
                </div>
            </>
        )
    }
}

b、函数式组件通过 useRef() 创建 【推荐】

这种方式只适合在函数式组件中使用
通过 .current 获取相应的值

import { useRef } from 'react'

export default function MyRefs() {
    // 使用 useRef  Hook 创建ref
    const myTextRef = useRef()
    const getText = () => {
        console.log('===myTextRef==', myTextRef)
        console.log(myTextRef.current.value)
        // 获取焦点
        // myTextRef.current.focus()
        // // 截取文本
        // console.log(myTextRef.current.value.substr(0, 5))
    }
  return (
    <div>
      <input type="text" ref={myTextRef} />
      <button onClick={getText}>测试</button>
    </div>
  )
}

c、回调函数的形式 创建 ref 【推荐】

这种创建的方式,在类式组件以及函数式组件中都可以使用
回调形式 通过 .value 获取相应的值

import { useRef, useEffect } from 'react'
export default function MyRefs() {

    let myRef2 = ''
    const setRef = (e) => {
      myRef2 = e
    }
    const getText2 = () => {
        console.log('===myRef2==', myRef2)
        console.log(myRef2.value)
    }
  return (
    <div>
      <hr />
      {/* 第一种直接将回调写在 jsx 中 */}
      {/* <input type="text" ref={e => myRef2 = e} /> */}
      {/* 第二种 传入一个回调函数 setRef */}
      <input type="text" ref={setRef} />
      <button onClick={getText2}>测试myRef2</button>
    </div>
  )
}

d、字符串形式 ref 【废弃不推荐

通过 this.refs.value 获取相应的值

export default class MyRefs extends Component{
  constructor() {
    super()
    this.state = {
      refSt: 'zifc'
    }
  }
  
  getText = () => {
    console.log('====', this.refs.zifc.value)
  }
  render() {
    return (
      <>
        <div>
          <input type="text" ref={this.state.refSt}></input>
          <button onClick={this.getText}>按钮</button>
        </div>
      </>
    )
  }
}

4、注意事项:推荐使用函数式组件useRef() 创建 ref

4.1、ref 变化时候,不会自动更新视图;
4.2、不能在渲染期间 对 ref 进行读写 current 的值,否则报错;如果需要在渲染期间 进行读写,需要修改为 state 属性,使用 其 set 方法进行更新;
4.3、可以在渲染 过程之外 对 ref 的值进行修改;

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;