• react中的refs


    概述

    很久之前就知道refs,感觉好神秘,恰好今天突然发现字符串形式的ref在官网不推荐使用了,于是好好总结一下ref的用法,供以后开发时参考,相信对其他人也有用。

    参考资料:
    Refs & DOM
    Forwarding Refs

    refs

    在react数据流中,可以通过props,refs和Context来访问其它组件的属性,其中利用refs可以在数据流外强制修改组件实例。

    需要注意的是,以前是通过给refs赋一个string,比如textInput,然后就可以通过this.refs.textInput来访问DOM节点,示例如下:

    import React, { Component } from 'react';
    
    class NoControl extends Component {
        constructor(props) {
            super(props);
            this.handleSubmit = this.handleSubmit.bind(this);
        }
        handleSubmit(e) {
            e.preventDefault();
            console.log(this.refs.name);
        }
    
        render() {
            return(
                <form onSubmit={this.handleSubmit}>
                    <input type="text" ref="name"/>
                    <button type="submit">Submit</button>
                </form>
            );
        }
    }
    
    export default NoControl;
    

    但是官网不推荐使用这种形式使用refs了,并且这种方法在未来的版本可能会被移除。官方建议使用回调的形式代替这种使用方式。

    refs的基本用法

    一般说来,我们需要在constructor里面初始化一个ref,然后就能在return里面用了,示例如下:

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.myRef = React.createRef();
      }
      render() {
        return <div ref={this.myRef} />;
      }
    }
    

    上面的this.myRef有一个current属性,它的值取决于下面三种情况:

    1. 如果ref属性被用于html元素,那么它的值是底层DOM元素。
    2. 如果ref属性被用于自定义类组件,那么它的值是已挂载的这个自定义类组件的实例。
    3. 函数式组件没有ref属性。

    另外,通过ref我们还可以调用这个自定义类组件的方法,示例如下:

    import React, { Component } from 'react';
    
    class CustomInput extends Component {
        constructor(props) {
            super(props);
            this.handleFocus = this.handleFocus.bind(this);
            this.myRef = React.createRef();
        }
    
        handleFocus(e) {
            this.myRef.current.focus();
        }
        render() {
            return(
                <input type="text" ref={this.myRef}/>
            )
        }
    
    }
    
    class NoControl extends Component {
        constructor(props) {
            super(props);
            this.handleSubmit = this.handleSubmit.bind(this);
            this.myRef = React.createRef();
        }
        handleSubmit(e) {
            e.preventDefault();
            this.myRef.current.handleFocus();
        }
    
        render() {
            return(
                <form onSubmit={this.handleSubmit}>
                    <CustomInput ref={this.myRef}/>
                    <button type="submit">Submit</button>
                </form>
            );
        }
    }
    
    export default NoControl;
    

    refs的回调用法

    由于refs里面的回调函数会在组件创建的时候自动生成。所以可以利用refs的回调用法,在组件创建的时候获得这个组件的一些信息,比如获得焦点等。示例如下:

    import React, { Component } from 'react';
    
    class NoControl extends Component {
        constructor(props) {
            super(props);
            this.handleSubmit = this.handleSubmit.bind(this);
            this.setElement = this.setElement.bind(this);
            this.myInput = null;
        }
    
        handleSubmit(e) {
            e.preventDefault();
            this.forceUpdate();
        }
    
        setElement(element) {
            this.myInput = element;
        }
    
        componentDidMount() {
            this.myInput.focus();
        }
        
        render() {
            return(
                <form onSubmit={this.handleSubmit}>
                    <input type="text" ref={this.setElement}/>
                    <button type="submit">Submit</button>
                </form>
            );
        }
    }
    
    export default NoControl;
    

    refs转发

    在使用HOC(高阶组件)的时候,我们是用一个类组件来对普通组件进行封装的,这个时候怎么获得里面这个普通组件的ref呢。

    react官方提供了React.forwardRef这个api来实现。示例如下:

    //NoControl.jsx
    import React, { Component } from 'react';
    import CustomInput from './CustomInput';
    
    class NoControl extends Component {
        constructor(props) {
            super(props);
            this.handleSubmit = this.handleSubmit.bind(this);
            this.myRef = React.createRef();
        }
        handleSubmit(e) {
            e.preventDefault();
            this.myRef.current.handleFocus();
            this.forceUpdate();
        }
    
        render() {
            return(
                <form onSubmit={this.handleSubmit}>
                    <CustomInput ref={this.myRef}/>
                    <button type="submit">Submit</button>
                </form>
            );
        }
    }
    
    export default NoControl;
    
    
    //CustomInput.jsx
    import React, { Component } from 'react';
    
    function logProps(Component) {
        class LogProps extends React.Component {
            componentDidUpdate(prevProps) {
                console.log('old props:', prevProps);
                console.log('new props:', this.props);
            }
            render() {
                console.log('HOC exists;');
                const { forwardedRef, ...rest } = this.props;
                return <Component ref={forwardedRef} {...rest} />;
            }
        }
        function forwardRef(props, ref) {
            return <LogProps {...props} forwardedRef={ref} />;
        }
        return React.forwardRef(forwardRef);
    }
    
    class CustomInput extends Component {
        constructor(props) {
            super(props);
            this.handleFocus = this.handleFocus.bind(this);
            this.myRef = React.createRef();
        }
    
        handleFocus(e) {
            this.myRef.current.focus();
        }
        render() {
            return(
                <input type="text" ref={this.myRef}/>
            );
        }
    }
    
    export default logProps(CustomInput);
    

    需要注意的是,forwardRef有第二个参数ref,然后它被React.forwardRef这个api封装,最后返回Component类组件。

  • 相关阅读:
    (零 ) 天猫精灵接入Home Assistant-总说明
    (二 -2) 天猫精灵接入Home Assistant-自动发现Mqtt设备
    (二 -1) 天猫精灵接入Home Assistant-控制Mqtt设备
    如何在关闭ssh连接的情况下,让程序继续运行?
    hass连接设备
    (一 ) 天猫精灵接入Home Assistant-服务器搭建
    (一) 天猫精灵接入Home Assistant- hass对接天猫精灵
    (3)HomeAssistant 连接MQTT
    (2)HomeAssistant 参数配置
    (1)HomeAssistant 安装开始
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/9633984.html
Copyright © 2020-2023  润新知