Skip to content
On this page

组件内容补充

ref基础

Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。 Ref 对于需要以常规DOM形式管理的组件非常有用,比如 input、button等,该特性对于可重用组件库非常有用

ref 属性可以接收的值有:

  1. 使用 useRef 创建的对象
  2. 回调函数。当 ref 属性是回调函数时,该函数接收 ref 所在 DOM 元素(也包括子DOM元素)或类实例(取决于元素的类型)作为其参数

应该谨慎使用 ref,如果发现过多地依赖ref才能使程序正常运行,请重新考虑数据流向

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

const Home = forwardRef(function(props, ref) {
  return (
    <div>
      <h2 ref={ref}>Home</h2>
      <button>按钮</button>
    </div>
  )
})

export default class App extends PureComponent {
  constructor(props) {
    super(props);

    this.homeTitleRef = createRef();
  }

  render() {
    return (
      <div>
        <Home ref={this.homeTitleRef}/>
        <button onClick={e => this.printInfo()}>打印ref</button>
      </div>
    )
  }

  printInfo() {
    console.log(this.homeTitleRef.current);
  }
}
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

HOC中使用refs

import React from 'react';

function logProps(WrappedComponent) {
  class LogProps extends React.Component {

    render() {
      const {aref, ...rest} = this.props  // 该this.props 指所有的包含常规props和ref参数的所有props,这里做一个解构
      return (
        <WrappedComponent {...rest} ref={aref}/>  // 这里的ref是固定语法,表明该DOM是我们想要获取的
      )
    }
  }

  return React.forwardRef((props, a) => {
    // props指的是name、age这样的常规的参数
    // a 指的是ref参数,forwardRef函数第二个参数就是用来传递ref值的
    return <LogProps {...props} aref={a}/>
  });
}


class FancyButton extends React.Component {
  render() {
    return (
      <>
        <h2>Fancy button</h2>
      </>
    )
  }
}

const EnhanceFancyButton = logProps(FancyButton);


class App extends React.Component {
  constructor(props) {
    super(props);

    this.fancyRef = React.createRef();

  }

  render() {
    return (
      <>
        <EnhanceFancyButton ref={this.fancyRef} name="lyx"/>
        <button onClick={e => this.printRef()} >button</button>
      </>
    )
  }
  printRef() {
    console.log(this.fancyRef);
  }
}

export default App;
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

Fragments

使用 Fragments 不会在DOM中创建额外的节点

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

// 短语法
render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

短语法不支持 key 或属性,若需要传递属性,需要使用Fragment