react进阶 react高阶组件和ref应用

高阶组件和ref

HOC 高阶组件

HOF:Higher-Order Function,高阶函数,以函数作为一个参数,返回一个参数
HOC:Higher-Order Component,高阶组件,以组件作为参数,返回一个组件

可以使用组件实现横切关注点。

注意

  1. 不要在render中使用高阶组件
  2. 不要在高阶组件中更改传入的组件

HocTestA

1
2
3
4
5
6
7
8
9
10
import React, { Component } from 'react'

export default class HocTestA extends Component {
render() {
return (
<div>HocTestA</div>
)
}
}

HocTestB

1
2
3
4
5
6
7
8
9
import React, { Component } from 'react'

export default class HocTestB extends Component {
render() {
return (
<div>HocTestB</div>
)
}
}

WithTestHoc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from "react";
/**
* 高阶组件
* @param {*} Comp 组件
* @returns
*/
export default function WithTest(Comp){
return class WithTestWrapper extends React.Component{
componentDidMount(){
console.log(`组件${Comp.name}被创建`);
}
render(){
return <>
<Comp {...this.props}></Comp>
</>
}
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from "react";
import WithTest from "./HOC/WithTestHoc";
import HocTestA from "./components/HocTestA";
import HocTestB from "./components/HocTestB";

const TestA = WithTest(HocTestA);
const TestB = WithTest(HocTestB)
export default class App extends Component {
render() {
return (
<>
<TestA></TestA>
<TestB></TestB>
</>
)
}
}

ref

reference:引用
直接使用dom中的某个方法,或使用组件中的某个方法。

  1. ref作用于内置的html组件,得到的将是真是的dom对象
  2. ref作用于类组件,将得到类的实例
  3. ref不能直接作用于函数组件,函数组件内部可以正常使用

ref不推荐使用字串符赋值,推荐使用函数或对象
字符串 要删除的使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { Component } from "react";

export default class Ref extends Component {
onHandleClick = ()=>{
// 读取input的输入值
console.log(this.refs.text.value)
}
render() {
return (
<>
<input ref="text" type="text" />
<button onClick={this.onHandleClick}>获取input的值</button>
</>
);
}
}

对象
通过React.createRef函数创建
对象结构

1
2
3
4
{
current:null,//刚创建时
}

可以通过current属性获取到引用的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { Component } from "react";

export default class Ref extends Component {
constructor(props){
super(props);
this.input = React.createRef()
}
onHandleClick = ()=>{
// 读取input的输入值
console.log(this.input.current.value)
}
render() {
return (
<>
<input ref={this.input} type="text" />
<button onClick={this.onHandleClick}>获取input的值</button>
</>
);
}
}

函数

函数的调用时间:

  1. componentDidMount的时候会调用该函数
  • 在componentDidMount事件中可以使用ref
  1. 如果ref的值发生了变动(旧的函数被新的函数替代),分别调用旧的函数和新的函数,时间点出现在componentDidUpdate之前
  • 旧的函数被调用时,传递参数为null
  • 新的函数被调用时,传递参数为引用对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { Component } from "react";

export default class Ref extends Component {
constructor(props){
super(props);
this.input = React.createRef()
}
onHandleClick = ()=>{
// 读取input的输入值
console.log(this.input.value)
}
render() {
return (
<>
<input ref={el=>this.input = el} type="text" />
<button onClick={this.onHandleClick}>获取input的值</button>
</>
);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React, { Component } from "react";

export default class Ref extends Component {
constructor(props){
super(props);
this.input = React.createRef()
}
onHandleClick = ()=>{
// 读取input的输入值
console.log(this.input.value)
}

getRef = (el)=>{
this.input = el
}
render() {
return (
<>
<input ref={this.getRef} type="text" />
<button onClick={this.onHandleClick}>获取input的值</button>
</>
);
}

ref转发

forwardRef:

  1. 参数:传递的只能是函数组件,不能是类组件,函数组件要有第二个参数来得到ref
  2. 返回值:返回一个新的组件

高阶组件 WithTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component } from "react";

export default function WithTest(Comp) {
class WithTest extends Component {
render() {
const { forwardRef, ...rest } = this.props;
return <Comp ref={forwardRef} {...rest}></Comp>;
}
}

return React.forwardRef((props,ref)=>{
return <WithTest {...props} forwardRef={ref}></WithTest>
})
}

组件CompA

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Component } from 'react'
import WithTest from './WithTest'

class CompA extends Component {
render() {
return (
<div>CompA
<h1> {this.props.data}</h1>
</div>
)
}
}
export default WithTest(CompA)

测试组件

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Component } from 'react'
import CompA from './CompA'
export default class Test extends Component {
compARef = React.createRef();
componentDidMount(){
console.log(this.compARef);//可以得到组件CompA的实例对象
}
render() {
return (
<CompA data="123456" ref={this.compARef}></CompA>
)
}
}