0
点赞
收藏
分享

微信扫一扫

手动实践一下react的forwardRef到底有啥作用

潇湘落木life 2022-03-12 阅读 57

首先,我们来看一下这个函数的使用实例

 const Son1 = React.forwardRef((props, ref) => {
            return (
                <div>
                    <p>this input is from Son1</p>
                    <input ref={ref} type='text' />
                </div>
            )
        })

很明显,上图其实利用函数创造了一个组件,明显将props参数和ref参数区分开来,将ref参数赋值和Son1组件的input子元素进行绑定,明显是直接越过了 Son1,这就是其第一个作用:将ref的传值穿透组件直达内部元素,我们可以看以下两个让input聚焦的写法

传统写法

// 创建一个子组件
        class Son extends React.Component {
            constructor(props) {
                super(props)
            }
            render () {
                return (
                    <div>
                        <p>this input is from Son</p>
                        <input type="text" ref={this.props.inputRef} /> //3.inputRef传递给ref
                    </div>

                )
            }
        }
 class Father extends React.Component {
            constructor(props) {
                super(props)
                this.inputRef = React.createRef()//1.创建
                this.handleClick = this.handleClick.bind(this)
            }
            handleClick () {
                this.inputRef.current.focus()
            }
            render () {
                return (
                    <div>
                        <Son inputRef={this.inputRef} /> //2.赋值给inputRef
                        <p>this button is from Father</p>
                        <br />
                        <button onClick={this.handleClick()}>点击让input聚焦</button>
                    </div>
                )
            }
        }

上图中ref的传递经过了三个步骤,接下来看一下新写法

 const Son1 = React.forwardRef((props, ref) => {
            return (
                <div>
                    <p>this input is from Son1</p>
                    <input ref={ref} type='text' />
                </div>
            )
        })
 class Father extends React.Component {
            constructor(props) {
                super(props)
                this.handleClick = this.handleClick.bind(this)
                this.input = React.createRef() //1.创建
            }
            handleClick () {
                // console.log(this.input.current);
                this.input.current.focus()
            }
            render () {
                return (
                    <div>
                        <Son1 ref={this.input} /> //2.ref直接穿透
                        <p>this button is from Father</p>
                        <br />
                        <button onClick={this.handleClick}>点击聚焦</button>
                    </div>
                )
            }
        }

新写法明显只有两个层级,省了一步,也就是说forwardRef就是用来传递ref的,和createRef一样,就是省了一步。

第二种用法就是forwardRef在高阶组件中的使用,我觉得官网上的例子没写好,上代码

  // 定义一个组件用作高阶组件的参数
        class Input extends React.Component {
            constructor(props) {
                super(props)
            }
            render () {
                return (
                    <input type='text' ref={this.props.Ref} />//6.Ref最终传给了input元素的ref
                )

            }
        }

        // 定义一个高阶组件, 目的是将参数上加上value
        function hoc (Component) {
            class Hoc extends React.Component {
                constructor(props) {
                    super(props)
                    this.val = "我是你爸爸"
                }

                render () {
                    const { forwardedRef, ...rest } = this.props
                    return (
                        <Component value={this.val} Ref={forwardedRef} {...rest} />//5.forwardedRef传给了高阶组件的参数的Ref
                    )
                }

            }
            return React.forwardRef((props, ref) => { //3.获得this.input
                return <Hoc {...props} forwardedRef={ref} />;//4.this.input传递给了forwardedRef
            });
        }

        // 组合高阶组件
        let SuperInput = hoc(Input)
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.handleClick = this.handleClick.bind(this)
                this.input = React.createRef() //1.创建
            }
            handleClick () {
                // console.log(this.input.current);
                this.input.current.focus()
            }
            render () {
                return (
                    <div>
                        <SuperInput ref={this.input} /> //2.传给ref
                        <button onClick={this.handleClick}>点击聚焦</button>
                    </div>
                )
            }
        }

这个传递还是比较丧心病狂的,表达能力有限,希望各位能够从我标的ref的传递顺序中了解这个api。

举报

相关推荐

0 条评论