Appearance
HOC
高阶组件
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式
具体而言,高阶组件是一个函数,其参数为组件,返回值为新的组件
用法
当多个组件的大部分实现都相同,仅有个别部分不同时,可以使用高阶组件进行复用。
HOC定义方式
import React, { PureComponent } from 'react';
class App extends PureComponent {
render() {
return (
<div>
hello world
</div>
)
}
}
// 类式高阶组件
function enhanceComponent(WrappedComponent) {
class newComponent extends PureComponent {
render() {
return (
// 通过这种方式可以接受传递来的参数
<WrappedComponent {...this.props}/>
)
}
}
// 组件的名称可以通过displayName属性来修改
newComponent.displayName = "hhh";
return newComponent
}
// 函数式高阶组件的写法
function enhanceComponent2(WrappedComponent) {
return props => {
return <WrappedComponent {...props}/>
}
}
const enhancementApp = enhanceComponent(App);
export default enhancementApp;
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
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
特点
- HOC 不能改变原始组件,也不能使用继承来复制行为
- 传递与HOC不相关的 props,可以理解为仅传递与被包裹组件相关的 props
- 不要在 render 方法中使用 HOC
- 复制静态方法。当你将 HOC 应用于组件时,原始组件将使用容器组件进行包装。这意味着新组件没有原始组件的任何静态方法。为了解决这个问题,你可以在返回之前把这些方法拷贝到容器组件上
HOC应用
增强props
import React, { Component } from "react";
function enhanceProps(WrapperCpn, otherProps) {
return (props) => <WrapperCpn {...props} {...otherProps}/>
}
class Header extends Component {
render() {
const {name, age, height} = this.props;
return (
<h2>Header {name + " " + age + " " + height}</h2>
)
}
}
class Main extends Component {
render() {
const {name, age} = this.props;
return (
<>
<h2>Main {name + " " + age}</h2>
<h3>{this.props.height}</h3>
</>
)
}
}
const EnhanceHeader = enhanceProps(Header, {height: 1.9})
const EnhanceMain = enhanceProps(Main, {height: 1.7})
class App extends Component {
render() {
return (
<div>
<EnhanceHeader name='lyx' age={19}/>
<EnhanceMain name='lyxCoder' age={199}/>
</div>
)
}
}
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
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
共享Context
import React, { PureComponent, createContext } from 'react';
const UserContext = createContext({
nickname: "默认",
level: -1
})
function withUser(WrapperCpn) {
return props => {
return (
<UserContext.Consumer>
{
value => {
return <WrapperCpn {...props} {...value}/>
}
}
</UserContext.Consumer>
)
}
}
function Header(props) {
const { nickname, level } = props;
return <h2>Header {"昵称:" + nickname + "等级:" + level}</h2>
}
function Footer(props) {
const { nickname, level } = props;
return <h2>Footer {"昵称:" + nickname + "等级:" + level}</h2>
}
const UserHeader = withUser(Header);
const UserFooter = withUser(Footer);
export default class App extends PureComponent {
render() {
return (
<div>
<UserContext.Provider value={{ nickname: "why", level: 90 }}>
<UserHeader />
<UserFooter />
</UserContext.Provider>
</div>
)
}
}
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
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
渲染判断鉴权
import React, { PureComponent } from 'react';
function loginAuth(Page) {
return props => {
if (props.isLogin) {
return <Page/>
} else {
return <LoginPage/>
}
}
}
function LoginPage() {
return <h2>LoginPage</h2>
}
function CartPage() {
return <h2>CartPage</h2>
}
const AuthCartPage = loginAuth(CartPage);
export default class App extends PureComponent {
render() {
return (
<div>
<AuthCartPage isLogin={true}/>
</div>
)
}
}
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
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
生命周期劫持
import React, { PureComponent } from 'react';
function logRenderTime(WrapperCpn) {
return class extends PureComponent {
UNSAFE_componentWillMount() {
this.begin = Date.now();
}
componentDidMount() {
this.end = Date.now();
const interval = this.end - this.begin;
console.log(`${WrapperCpn.name}渲染使用时间:${interval}`)
}
render() {
return <WrapperCpn {...this.props}/>
}
}
}
class Home extends PureComponent {
render() {
return (
<div>
<h2>Home</h2>
<p>我是home的元素,哈哈哈</p>
</div>
)
}
}
class Detail extends PureComponent {
render() {
return (
<div>
<h2>Detail</h2>
<p>我是detail的元素,哈哈哈</p>
</div>
)
}
}
const LogHome = logRenderTime(Home);
const LogDetail = logRenderTime(Detail);
export default class App extends PureComponent {
render() {
return (
<div>
<LogHome />
<LogDetail />
</div>
)
}
}
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
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
redux connct函数
在 redux
中,为了减少组件调用 store
时的重复代码,将 store
订阅、注销通过 HOC
复用,将state
、dispatch
以 props
的形式传递给目标组件
function connect (mapStateToProps, mapDispatchToProps) {
return function handleMapCpn (WrappedComponent) {
return class extends React.Component {
// 使用HOC的目的就是抽取出公共的代码,将state、函数以props的形式传递给目标组件
constructor(props) {
super(props);
this.state = {
storeState: mapStateToProps(store.getState())
}
}
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.setState({
storeState: mapStateToProps(store.getState())
})
})
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
console.log(this.props)
return <WrappedComponent {...this.props}
{...mapStateToProps(store.getState())}
{...mapDispatchToProps(store.dispatch)}/>
}
}
}
}
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
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