759 字
4 分钟
03.受控和非受控组件
2025-03-28

refs#

refs的使用#

目前创建 refs 来获取对应DOM的方式有三种:

  1. 传入字符串:

使用时通过 this.refs. 传入的字符串格式获取对应的元素;

class App extends PureComponent {
  render() {
    return (
      <div>
        <p ref='titleRef'>Hello React</p>
        <button onClick={e => this.handleClick()}>改变文本</button>
      </div>
    )
  }
  handleClick() {
    this.refs.titleRef.innerHTML = 'Hello Friend'
  }
}
  • 传入一个对象:(推荐)

对象是通过 React.createRef() 方式创建出来的;

使用时获取到创建的对象其中有一个current属性就是对应的元素;

import React, { PureComponent, createRef } from 'react'

class App extends PureComponent {
  constructor(props) {
    super(props)

    this.titleRef = createRef()
  }
  render() {
    return (
      <div>
        <p ref={this.titleRef}>Hello React</p>
        <button onClick={e => this.handleClick()}>改变文本</button>
      </div>
    )
  }
  handleClick() {
    console.log(this.titleRef.current)
  }
}
  • 传入一个函数:

该函数会在DOM被挂载时进行回调,这个函数会传入一个元素对象,我们可以自己保存;

使用时,直接拿到之前保存的元素对象即可。

class App extends PureComponent {
  constructor(props) {
    super(props)
    this.titleEl = null
  }
  render() {
    return (
      <div>
        <p ref={arg => this.titleEl = arg}>Hello Boy</p>
        <button onClick={e => this.handleClick()}>改变文本</button>
      </div>
    )
  }
  handleClick() {
    this.titleEl.innerHTML = 'Hello Girl'
  }
}

ref的类型#

ref 的值根据节点的类型而有所不同:

  • 当 ref 属性用于HTML元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性;

  • 当 ref 属性用于自定义类组件时,ref 对象接收组件的挂载实例作为其 current 属性;

  • 你不能在函数组件上使用 ref 属性,因为他们没有实例。

这个时候我们可以通过 React.forwardRef,或者使用hooks。

ref的转发#

如果想对函数组件添加 ref 且不使用 hooks 的话,需要使用 forwardRef 这个高阶组件:

import React, { PureComponent, createRef, forwardRef } from 'react'

class App extends PureComponent {
  constructor(props) {
    super(props)

    this.profileRef = createRef()
  }
  render() {
    return (
      <div>
        <Profile ref={this.profileRef}></Profile>
        <button onClick={e => this.showRef()}>打印Ref</button>
      </div>
    )
  }

  showRef() {
    console.log(this.profileRef.current)
  }
}


// 高阶组件,用 Profile 接收返回的新组件
// 并对传入的组件进行了一个增强,我们需要对传入的组件再传入一个参数
const Profile = forwardRef(function (props, ref) {
  return (
    <div>
      <h2 ref={ref}>Profile</h2>
    </div>
  )
})

export default App;

受控组件#

使用DOM默认处理HTML表单(<input>、<textarea>等)的组件,被称为受控组件。

在 React 中,可变状态通常保存在组件的 state 属性中,并且只能通过使用 setState() 来更新。

  • 我们将两者结合起来,使 React 的 state 成为“唯一数据源”;

  • 渲染表单的 React 组件还控制着用户输入过程中表单发生的操作;

  • 被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。

非受控组件#

非受控组件也就是一个独立组件,不需要传值也无任何与当前组件的父组件有所交集,在我们封装组件的时候,只有在当前组件只做展示用途且无任何不同的时候才会封装为非受控组件。

例如:轮播组件等等。

03.受控和非受控组件
https://sytusramlethal.github.io/posts/03受控和非受控组件/
作者
Sytus Ramlethal
发布于
2025-03-28
许可协议
CC BY-NC-SA 4.0