23-非受控组件Ref相关操作的回顾

86 阅读1分钟

非受控组件

  • 不受状态管理的组件(可以基于ref获取Dom元素进行操作);
  • 使用方式如下
    • ref="xxx" 不推荐使用
    • ref={x => this.xxx = x}
    • React.createRef
  • 一般的使用ref的场景
    • 赋值给标签,获取dom元素
    • 赋值给类组件, 获取子组件的实例(调用里面的方法等)
    • 函数组件不能直接设置, 但是可以基于 React.forwardRef进行ref的转发
import React, { PureComponent, createRef } from 'react'

export default class MyRef extends PureComponent {
  constructor() {
    super();
    // 建议在这里使用,只会执行一次,这样 createRef不用反复创建了
    this.cRef = createRef();
  }
  state = {
    num: 0
  }
  box = null
  handle = () => {
    this.setState({
      num: this.state.num + 1
    })
  }
  handle1 = () => {
    // 严格模式下:这是不安全的写法(不推荐使用)
    this.refs.box.innerHTML++;
  }
  handle2 = () => {
    // ref是一个函数,在视图渲染的时候会把函数执行;传递进来的实参就是当前标签的dom对象
    console.log(this.box);
    this.box.innerHTML++;
  }
  handle3 = () => {
    this.cRef.current.innerHTML++;
  }
  render() {
    return (
      <div style={{padding: '20px'}}>
        <span>{ this.state.num }</span>
        <br />
        <button onClick={this.handle}>plus by state</button>
        <hr />
        <div ref="box" style={{marginTop: '20px'}}>0</div>
        <button onClick={this.handle1}>plus by ref1</button>
        <hr />
        <div ref={x => this.box = x} style={{marginTop: '20px'}}>0</div>
        <button onClick={this.handle2}>plus by ref2</button>
        <hr />
        <div ref={this.cRef} style={{marginTop: '20px'}}>0</div>
        <button onClick={this.handle3}>plus by ref3</button>
      </div>
    )
  }
}

image.png

父组件传递给子组件

  • 直接赋值给函数子组件会报错,子组件需要用forwordRef包裹,进行ref转发
    • 原因是函数组件没有实例
// => Parent.jsx
import React, { PureComponent, createRef } from 'react'
import Son from './Son'
import Son2 from './Son2'

export default class Parent extends PureComponent {
  cRef1 = createRef();
  cRef2 = createRef();

  componentDidMount() {
    console.log(this.cRef1, this.cRef2)
  }
  render() {
    return (
      <div>
        <Son ref={this.cRef1}/>
        <Son2 ref={this.cRef2}/>
      </div>
    )
  }
}
// => Son.jsx 类子组件
import React, { PureComponent } from 'react'

export default class Son extends PureComponent {
  render() {
    return (
      <div>Son</div>
    )
  }
}
// => Son.jsx 函数子组件
import React, { forwardRef } from 'react'

const Son2 = forwardRef((props, ref) => {
  return (
    <div>
      <span>Son2</span>
      <div ref={ref}>我是有ref了</div>
    </div>
  )
})

export default Son2;

image.png