掌握React基础知识第五章-Ref和Refs

940 阅读2分钟

2022即将到来,前端发展非常迅速,现在的前端已经不再是写写简单的页面了,伴随着web大前端,工程化越来越火,也出现了很多框架。很多公司也不单单是使用单一的框架了,作为前端开发国内最火的两大框架,都是必须要掌握的。所以,我决定在这疫情肆虐的年底把React学习一下,也为自己将来找工作多一分竞争力...

学习阶段,如有不对之处,欢迎评论区留言,我及时更正

本文已连载,其它章节传送门⬇️

第一章-jsx语法认识

第二章-函数组件和class类组件

第三章-Props和State

第四章-事件处理

第六章-生命周期

第七章-跨组件通信Context

第八章-React Hooks

Ref和Refs

Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素,React中的ref类似于vue中的ref,都可以通过给组件或者Dom绑定ref获取到此组件实例

注意:字符串形式的ref已经弃用

我们有三种方法可以创建ref,分别为:字符串形式的ref(已弃用)、回调形式的ref、createRef

字符串形式的ref

export default class Demo extends Component {
	componentDidMount(){
    console.log(this.refs.Index)
  }
  render() {
    return (
      <div>
        <Index ref="Index"></Index>
      </div>
    )
  }
}

class Index extends Component {
  render() {
    return (
      <div>
        <button>Index按钮</button>
      </div>
    )
  }
}

image.png 我们可以给组件绑定ref属性,在componentDidMount 钩子函数中通过this.refs.绑定ref名访问到组件实例,打印结果可以看到,但是此方法已弃用,官网也有说明此方法会有一些问题

回调形式的ref

export default class Demo extends Component {
  constructor(props){
    super(props)
    this.indexDOM = null
  }
  getIndexRef = (element) => {
		console.log(element, 'getIndexRef函数执行了')
    this.indexDOM = element
  }
  render() {
    return (
      <div>
        <Index ref={this.getIndexRef}></Index>
      </div>
    )
  }
}

class Index extends Component {
  render() {
    return (
      <div>
        <button>Index按钮</button>
      </div>
    )
  }
}

借用上面的图片吧,也是可以正常打印能拿到组件。但是如果ref的回调函数是内联形式的,更新过程中,会被执行两次,第一次传入null,第二次传入dom节点,这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题

我们修改下代码:

export default class Demo extends Component {
  constructor(props){
    super(props)
    this.indexDOM = null
    this.state = {
      count: 0
    }
  }
  getIndexRef = (element) => {
    console.log(element, 'getIndexRef函数执行了')
    this.indexDOM = element
  }
  handleClick = () => {
    this.setState({
      count: this.state.count + 1
    })
  }
  render() {
    return (
      <div>
        <Index ref={e => this.getIndexRef(e)} changeCount={this.handleClick} count={this.state.count}></Index>
      </div>
    )
  }
}

class Index extends Component {
  
  render() {
    return (
      <div>
        <h1>当前count:{this.props.count}</h1>
        <button onClick={this.props.changeCount}>Index按钮</button>
      </div>
    )
  }
}

image.png

第一次正常打印,当我点击按钮触发组件更新的时候,可以看到 ref的内联回调函数执行了两次且第一次拿到的是null

createRef

通过React.createRef 创建并绑定ref,也可以访问到组件节点,官网推荐使用此方法

export default class Demo extends Component {
  constructor(props){
    super(props)
    this.myIndex = React.createRef()
  }
  componentDidMount() {
    console.log(this.myIndex.current)
  }
  render() {
    return (
      <div>
        <Index ref={this.myIndex}></Index>
      </div>
    )
  }
}

class Index extends Component {
  render() {
    return (
      <div>
        <button>Index按钮</button>
      </div>
    )
  }
}