25 Refs转发机制与在高阶组件中的使用

本文探讨了在React.js中如何将子节点的ref暴露给父节点,以及在16.3及以上版本和16.2及以下版本中Refs的转发机制,包括props传递、回调方法、父组件回调等不同方式。同时,介绍了在高阶组件中如何实现Refs的转发,以及使用过程中需要注意的事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

将子节点的ref暴露给父节点

  • 16.3以上 Refs转发,将ref自动通过组件传递给子组件
1. 在父组件创建ref对象
2. 给子组件赋值ref
3. 通过React.forward向子组件转发ref属性
4. 父组件的ref对象指向子组件dom
5. ref参数只有在 React.forwardRef 组件内定义时可接受
const MyInput = React.forwardRef((props, ref) =>
    <input type="text" placeholder={props.placeholder} ref={ref} />
)
class App extends React.Component {
    constructor(props) {
        super(props)
        this.refInApp = React.createRef()
    }
    componentDidMount() {
        console.log('【APP】componentDidMount', this.refInApp)
    }
    inputOperate = () => {
        const oInput = this.refInApp.current
        oInput.focus()
    }
    render() {
        return (
            <>
                <MyInput ref={this.refInApp} placeholder="请输入" />
                <button onClick={this.inputOperate}>聚焦</button>
            </>
        )
    }
}
ReactDOM.render(
    <App />,
    document.getElementById('app')
)

在这里插入图片描述

在高阶组件中转发

  • 匿名改具名
    在这里插入图片描述
class MyInput extends React.Component {
    render() {
        return (
            <input type="text" />
        )
    }
}
function InputHoc(WrapperComponent) {
    class Input extends React.Component {
        render() {
            // 容器组件内部获取ref属性
            const { forwardedRef, ...props } = this.props
            return (
                // 将forwardedRef传递给参数组件
                <WrapperComponent ref={forwardedRef} {...props} />
            )
        }
    }
    // return React.forwardRef((props, ref) => {
    //     return <Input {...props} forwardedRef={ref} />
    // })

    // 向子组件传递ref 
    function forwardRef(props, ref) {
        return <Input {...props} forwardedRef={ref} />
    }
    forwardRef.displayName = 'Input-' + WrapperComponent.name
    return React.forwardRef(forwardRef)

}
const MyInputHoc = InputHoc(MyInput)
class App extends React.Component {
    constructor(props) {
        super(props)
        this.refInApp = React.createRef()
    }
    componentDidMount() {
        // 拿到高阶组件包裹的MyInput的实例
        console.log('【APP】componentDidMount', this.refInApp)
    }
    inputOperate = () => {
        const oInput = this.refInApp.current
        oInput.focus()
    }
    render() {
        return (
            <>
                {/* 用ref接收转发的ref */}
                <MyInputHoc ref={this.refInApp} placeholder="请输入" />
                <button onClick={this.inputOperate}>聚焦</button>
            </>
        )
    }
}
ReactDOM.render(
    <App />,
    document.getElementById('app')
)

16.2及以下 Refs转发

1. props传递

class MyInput extends React.Component {
    render() {
        return (
            <input type="text" ref={this.props.inputRef} placeholder={this.props.placeholder} />
        )
    }
}
class App extends React.Component {
    constructor(props) {
        super(props)
        this.refInApp = React.createRef()
    }
    componentDidMount() {
        console.log('【APP】componentDidMount', this.refInApp)
    }
    inputOperate = () => {
        const oInput = this.refInApp.current
        oInput.focus()
    }
    render() {
        return (
            <>
                {/* 用ref接收转发的ref */}
                <MyInput inputRef={this.refInApp} placeholder="请输入" />
                <button onClick={this.inputOperate}>聚焦</button>
            </>
        )
    }
}
ReactDOM.render(
    <App />,
    document.getElementById('app')
)

2. 回调

在这里插入图片描述

class MyInput2 extends React.Component {
    constructor(props) {
        super(props)
        this.innerInput = null
    }
    setMyInput = (el) => {
        // 这里就是dom,没有包裹在对象里
        console.log('回调的方式el', el)
        this.innerInput = el;
    }
    inputOperate = () => {
        this.innerInput.value = ''
        this.innerInput.focus()
    }

    render() {
        return (
            <>
                <input type="text" ref={this.setMyInput} />
                <button onClick={this.inputOperate}>聚焦(回调方式)</button>
            </>
        )
    }
}

3. 在父组件回调

class MyInput3 extends React.Component {
    render() {
        return (
            <input type="text" ref={this.props.inputRef} />
        )
    }
}
class App extends React.Component {
    componentDidMount() {
        // 在父组件获取到子组件的dom,不是包裹在对象里的
        console.log('【APP】componentDidMount', this.oInput)
    }
    inputOperate2 = () => {
        this.oInput.focus()
    }
    render() {
        return (
            <>
                <MyInput3 inputRef={el => this.oInput = el} />
                <button onClick={this.inputOperate2}>聚焦(回调2,定义在父组件)								 	 </button>
            </>
        )
    }
}

4. 字符串形式 已废弃

  • 依赖组件实例下面的refs集合里的ref
  • 需要React保持追踪当前正在渲染的组件(没有加载完成,this没法确定)
  • 可能会比较慢
  • 不能在render中工作
  • 不能组合,只能有一个ref属性
class App extends React.Component {
    componentDidMount() {
        console.log('【APP】componentDidMount字符串',this.refs.inputRefText)
    }
    render() {
        return (
            <>
                <input type="text" ref="inputRefText" />
            </>
        )
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值