React中的Ref创建

1. ref用string 来表示 ,React中已将它废弃, 原因有:

  • 静态类型检测不支持
  • 无法混淆压缩
  • 易产生挂载位置歧义
  • 根组件无法使用

2.React.createRef()

  • React.createRef()应用在html dom元素上的时候,dom元素赋值给React.createRef().current属性上。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Parent extends React.Component {
    constructor(props) {
    super(props);
    this.rt = React.createRef();
    }
    componentDidMount() {
    this.rt.current.focus();
    }
    render(){
    return(
    <input ref={this.rt} />
    )
    }
    }
  • 当React.createRef()应用在class的Component上时,React.createRef().current上的值是Component的实例,所以不能将React.createRef()生成的值赋给Function Component,即无状态组件,因为他们没有实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 class Child extends React.Component {
constructor(props) {
super(props);
this._ref = React.createRef();
this.focusInput = this.focusInput.bind(this);
}

focusInput() {
this._ref.current.focus();
};

render() {
return (
<input ref={this._ref} />
)
}
}

class Parent extends React.Component {
constructor(props) {
super(props);
this.rt = React.createRef();
}
componentDidMount() {
this.rt.current.focusInput();
}
render(){
return(
<Child ref={this.rt} />
)
}
}

3.React.forwardRef()
通常我们对高阶组件添加ref属性,只能获取包裹的组件,而不能获取被包裹的组件,通过React.forwardRef()可以将ref属性从父组件传递到子组件中。
ref 是一个特殊的属性在react里,仅当使用React.forwardRef作为第二个参数时才存在,如果作为普通的函数和Component中作为props传递是不存在的。
使用场景有以下2种,一般使用于高阶组件传递ref。

  1. ref通过forwardRef直接传递到DOM node上 。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const FocusInput = React.forwardRef((props, ref) => {
    return <input ref={ref} />
    });

    class App extends React.Component{
    constructor(props) {
    super(props);
    this.ref = React.createRef();
    }
    componentDidMount(){
    this.ref.current.focus();
    }
    render() {
    return <FocusInput ref={this.ref} />
    }
    }
  2. 在高阶组件中传递ref 到子组件中,得到子组件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    function wrapperWithChild(WrappedComponent) {
    class Child extends React.Component {
    render() {
    return <WrappedComponent ref={this.props.innerRef} />
    }
    }
    return React.forwardRef((props, ref) => {
    return <Child {...props} innerRef={ref} />
    });
    }

    class Wrap extends React.Component {
    render(){
    return <input className='input' />;
    }
    }

    const Child = wrapperWithChild(Wrap);

    class Parent extends React.Component {
    constructor(props) {
    super(props);
    this.rt = React.createRef();
    }
    componentDidMount() {
    console.log(this.rt.current); //这边this.rt.current得到的是Wrap组件
    }
    render(){
    return(
    <Child ref={this.rt} />
    )
    }
    }
    ReactDOM.render(<Parent />, document.getElementById('root'));

4.回调函数 Ref

  • 直接作用在DOM元素上获取该元素
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Parent extends React.Component {
    constructor(props) {
    super(props);
    this.rt = null;
    }
    componentDidMount() {
    this.rt.focus();
    }
    render(){
    return(
    <input ref={ref => this.rt = ref} />
    )
    }
    }
  • 可以通过像一个props 命名为任何字符除了ref 传递给其他组件,也可以在HOC中传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Child extends React.Component {
render(){
return <input ref={this.props.innerRef} />;
}
}

class Parent extends React.Component {
constructor(props) {
super(props);
this.rt = null;
}
componentDidMount() {
this.rt.focus();
}
render(){
return(
<Child innerRef={ref => this.rt = ref} />
)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//高阶组件中传递使用例子
function wrapperWithChild(WrappedComponent) {
class Child extends React.Component {
render() {
return <WrappedComponent ref={this.props.innerRef} />
}
}
return Child;
}

class Wrap extends React.Component {
render(){
return <input className='input' />;
}
}

const Child = wrapperWithChild(Wrap);

class Parent extends React.Component {
constructor(props) {
super(props);
this.rt = null;
}
componentDidMount() {
console.log(this.rt); //这边this.rt得到的是Wrap组件
}
render(){
return(
<Child innerRef={ref => this.rt = ref} />
)
}
}
ReactDOM.render(<Parent />, document.getElementById('root'));

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!