@toc
高阶组件
let Root = props => <div>{props.schoolName}</div>;
如果要在上例的Root组件进行增强怎么办?例如将Root组件的div外部再加入其它div
柯里化这个Wrapper函数1
2
3
4
5
6
7
8
9
10
11let Wrapper = function (Component, props) {
return (
<div>
{props.schoolName}
<hr />
<Component />
</div>
);
};
let Root = props => <div>{props.schoolName}</div>;
柯里化这个Wrapper函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import React from 'react';
import ReactDom from 'react-dom';
let Wrapper = function (Component) {
function _wrapper(props) {
return (
<div>
{props.schoolName}
<hr />
<Component />
</div>
);
}
return _wrapper;
};
let Root = props => <div>Root</div>;
let NewComp = Wrapper(Root) // 返回一个包装后的元素
ReactDom.render(<NewComp schoolName="Hello World"/>, document.getElementById('root'));
下面代码本身就是一个无状态组件,内部包裹这一个传入的组件,可以看做增强了传入的组件
- 传入的组件作为返回的新组件的子组件
1
2
3
4
5
6
7
8
9function _wrapper(props) {
return (
<div>
{props.schoolName}
<hr />
<Component />
</div>
);
}
- 传入的组件作为返回的新组件的子组件
那么上面代码的Wrapper函数可以看做参数是一个组件,返回一个新组件,即高阶组件
简化Wrapper,箭头函数
1
2
3
4
5
6
7
8
9
10
11let Wrapper = function (Component) {
return (props) => {
return (
<div>
{props.schoolName}
<hr />
<Component />
</div>
);
};
};
再次变化1
2
3
4
5
6
7
8
9
10let Wrapper = function (Component) {
return props =>
(
<div>
{props.schoolName}
<hr />
<Component />
</div>
);
};
再次变化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import React from 'react';
import ReactDom from 'react-dom';
let Wrapper = Component => props =>
(<div>
{props.schoolName}
<hr />
<Component />
</div>);
let Root = props => <div>Root</div>;
let NewComp = Wrapper(Root)
ReactDom.render(<NewComp schoolName="Hello World" />, document.getElementById('root'));
装饰器
新版ES 2016中增加了装饰器的支持,因此可以使用装饰器来改造上面的代码1
2@Wrapper // 这是不对的,装饰器装饰函数或类
let Root = props => <div>Root</div>;
ES 2016的装饰器只能装饰类,所以,将Root改写成类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import React from 'react';
import ReactDom from 'react-dom';
let Wrapper = Component => props =>
(<div>
{props.schoolName}
<hr />
<Component />
</div>);
@Wrapper
class Root extends React.Component {
render() {
return <div>Root</div>;
}
}
ReactDom.render(<Root schoolName="Hello World" />, document.getElementById('root'));
如何让Root也显示出schoolName?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import React from 'react';
import ReactDom from 'react-dom';
let Wrapper = Component => props =>
(<div>
{props.schoolName}
<hr />
<Component {...props} />
</div>);
@Wrapper
class Root extends React.Component {
render() {
return <div>{this.props.schoolName}</div>;
}
}
ReactDom.render(<Root schoolName="Hello World" />, document.getElementById('root'));
使用 <Component {...props} />
相当于给组件增加了属性
带参装饰器
想给装饰器函数增加一个id参数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import React from 'react';
import ReactDom from 'react-dom';
// 带参装饰器函数
let Wrapper =
id => Component => props =>
(<div id={id}>
{props.schoolName}
<hr />
<Component {...props} />
</div>);
@Wrapper('wrapper') // 带参
class Root extends React.Component {
render() {
return <div>{this.props.schoolName}</div>;
}
}
ReactDom.render(<Root schoolName="Hello World" />, document.getElementById('root'));
通过上面的改写,就得到带参装饰器
如果觉得不好接受,可以先写成原始的形式,熟悉了箭头函数语法后,再改成精简的形式