1.基本概念
高阶组件是参数为组件,返回值为新组件的函数。
2.举例说明
① 装饰工厂模式
组件是 react 中的基本单元,组件中通常有一些逻辑(非渲染)需要复用处理。这里我们可以用高阶组件对组件内部中的一些通用进行封装。
未封装时,相同的逻辑无法复用:
渲染评论列表
class CommentList extends React.Component { constructor(props) { super(props); 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> ); } }
渲染博客列表
lass 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} />; } }
借用高阶组件,封装公用逻辑:
const CommentListWithSubscription = withSubscription( CommentList, (DataSource) => DataSource.getComments() ); const BlogPostWithSubscription = withSubscription( BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id) );
组件加工(加工:处理公用逻辑)工厂,接受旧组件,返回新组件:
// 此函数接收一个组件... 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() { // ... 并使用新数据渲染被包装的组件! // 请注意,我们可能还会传递其他属性 return <WrappedComponent data={this.state.data} {...this.props} />; } }; }
233