用簡單的話來說,主要是爲了更大程度的複用現有代碼,抽離代碼而產生的一個模式
高階組件的參數可以爲一個組件,通過一個組件再去生成另一個組件
用官方的例子來解釋:
現有一個CommentList組件如下
class CommentList extends React.Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this);
this.state = {
// "DataSource" 就是全局的數據源
comments: DataSource.getComments()
};
}
componentDidMount() {
// 添加事件處理函數訂閱數據
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
// 清除事件處理函數
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
// 任何時候數據發生改變就更新組件
this.setState({
comments: DataSource.getComments()
});
}
render() {
return (
<div>
{this.state.comments.map((comment) => (
<Comment comment={comment} key={comment.id} />
))}
</div>
);
}
}
同時有另一個BlogPost組件如下:
class BlogPost extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
blogPost: DataSource.getBlogPost(props.id)
};
}
componentDidMount() {
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
blogPost: DataSource.getBlogPost(this.props.id)
});
}
render() {
return <TextBlock text={this.state.blogPost} />;
}
}
可以看出這兩個組件中的結構基本一致,都是通過DataSource接收數據,然後監聽,解除監聽,然後渲染
那麼我們就可以將公共的部分提取出來,如下:
// 函數接受一個組件參數……
function withSubscription(WrappedComponent, selectData) {
// ……返回另一個新組件……
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ……注意訂閱數據……
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ……使用最新的數據渲染組件
// 注意此處將已有的props屬性傳遞給原組件
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
然後就可以通過withSubscription組件來生成新的組件:
const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id)
);