美文网首页
React高阶组件

React高阶组件

作者: 蛮吉大人123 | 来源:发表于2018-06-25 15:24 被阅读22次

介绍

将高阶组件之前先讲高阶函数,所谓高阶函数,就是接受一个或多个函数作为输入,或者输出一个一个函数的函数。而高阶组件其实接收React组件作为输入,输出一个新的React组件的组件。

a higher-order component is a function that takes a component and returns a new component.

react官网对高阶组件的介绍只是从语义上予以理解,并不能真的运行起来, 下面举一个简化版的例子,结合这个例子再去看官网上给出的实际运用会更加的清楚。

运用

一个通过获取外部数据来展示评论列表的组件可能如下所示:

class CommentList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      comments: [],
    };
  }

  componentDidMount() {
    // 获取评论列表
    this.getComments();
  }

  getComments = () => {
    // 模拟ajax请求获取数据
    setTimeout(() => {
      const comments = [
        { title: 'React是一个纯View层', description: '不擅长于和动态数据打交道,因此它不同于,也替代不了常规的MV*框架;', id: '0' },
        { title: 'React很擅长于处理组件化的页面', description: ',在页面上搭组件的形式有点像搭乐高一样,因此用上React的项目需求常规为界面组件化。另外React只支持到IE8+,就天朝的情况,是否使用React还是得稍微斟酌一番。', id: '1' },
        { title: 'React是一个纯View层', description: '不擅长于和动态数据打交道,因此它不同于,也替代不了常规的MV*框架;', id: '2' },
        { title: 'React很擅长于处理组件化的页面', description: ',在页面上搭组件的形式有点像搭乐高一样,因此用上React的项目需求常规为界面组件化。另外React只支持到IE8+,就天朝的情况,是否使用React还是得稍微斟酌一番。', id: '3' },
      ];
      this.setState({ comments });
    }, 2000);
  }

  toggleClick(index) {
    // 点击显示详情
    this.setState(prevState => ({
      comments: prevState.comments.map((comment, i) => (
        Object.assign({}, comment, { showDesc: i === index ? !comment.showDesc : comment.showDesc })
      )),
    }));
  }

  render() {
    return (
      <div>
        {this.state.comments.map((comment, index) => (
          <p key={comment.id}>
            列表{comment.title} {comment.showDesc && comment.description}
            <a onClick={this.toggleClick.bind(this, index)}>{comment.showDesc ? '收起' : '展开'}</a>
          </p>
        ))}
      </div>
    );
  }
}

一个展示单个博客帖子的组件,可能如下所示:

class BlogPost extends Component {
  constructor(props) {
    super(props);
    this.state = {
      blogPost: {},
    };
  }

  componentDidMount() {
    // 获取评论列表
    this.getComments();
  }

  getComments = () => {
    // 模拟ajax请求获取数据
    setTimeout(() => {
      const blogPost = { title: 'React是一个纯View层', description: '不擅长于和动态数据打交道,因此它不同于,也替代不了常规的MV*框架;', id: '0' };
      this.setState({ blogPost });
    }, 2000);
  }

  render() {
    const { blogPost } = this.state;
    return (
      <div>
        <h2>博客:</h2>
        {
          blogPost.id
          &&
          <p key={blogPost.id}>
            {blogPost.title} {blogPost.showDesc && blogPost.description}
          </p>
        }
      </div>
    );
  }
}

这个时候你会发现他们的大部分功能是一样的,那这个样能不能简化一下将公共的部分抽离出来, 这时候就需要高阶函数登场了,大概是这样写的:

function withSubscription(type) {
  return (WrappedComponent) => {
    return class extends Component {
      constructor(props) {
        super(props);
        this.state = {};
      }
    
      componentDidMount() {
        // 获取评论列表
        this.getComments();
      }
  
      getComments = () => {
        // 模拟ajax请求获取数据
        setTimeout(() => {
          if (type === 'blog') {
            const blogPost = { title: 'React是一个纯View层', description: '不擅长于和动态数据打交道,因此它不同于,也替代不了常规的MV*框架;', id: '0' };
            this.setState({ dataSource: blogPost });
          } else if (type === 'comment') {
            const comments = [
              { title: 'React是一个纯View层', description: '不擅长于和动态数据打交道,因此它不同于,也替代不了常规的MV*框架;', id: '0' },
              { title: 'React很擅长于处理组件化的页面', description: ',在页面上搭组件的形式有点像搭乐高一样,因此用上React的项目需求常规为界面组件化。另外React只支持到IE8+,就天朝的情况,是否使用React还是得稍微斟酌一番。', id: '1' },
              { title: 'React是一个纯View层', description: '不擅长于和动态数据打交道,因此它不同于,也替代不了常规的MV*框架;', id: '2' },
              { title: 'React很擅长于处理组件化的页面', description: ',在页面上搭组件的形式有点像搭乐高一样,因此用上React的项目需求常规为界面组件化。另外React只支持到IE8+,就天朝的情况,是否使用React还是得稍微斟酌一番。', id: '3' },
            ];
            this.setState({ dataSource: comments });
          }
        }, 2000);
      }
      render() {
        return (
          <WrappedComponent dataSource={this.state.dataSource} {...this.props} />
        );
      }
    }
  }
}

这样的话CommentList组件和BlogPost组件就可以以一种很简洁的方式去书写

@withSubscription('comment')
export default class CommentList extends Component {
  render() {
    const { dataSource: comments } = this.props;
    return (
      <div>
        <h2>评论列表:</h2>
        {
          comments
          &&
          comments.map(comment => (
            <p key={comment.id}>
              {comment.title} {comment.description}
            </p>
          ))}
      </div>
    );
  }
}

@withSubscription('blog')
export default class BlogPost extends Component {
  render() {
    const { dataSource: blogPost } = this.props;
    return (
      <div>
        <h2>博客:</h2>
        {
          blogPost && blogPost.id
          &&
          <p key={blogPost.id}>
            {blogPost.title} {blogPost.description}
          </p>
        }
      </div>
    );
  }
}

这里只是抽离出来了一个type,如果是为了高阶函数的通用性的话,可以参考官网给出的例子去动态获取数据而不是直接在组件里分类来获取数据

个人觉得React高阶组件的特点有两个:

  1. 普通高阶函数的好处,可以将一些公共的组件,逻辑抽离出来,简化书写。
  2. 他可以通过props进行数据的传递。

相关文章

  • 利用 React 高阶组件实现一个面包屑导航

    什么是 React 高阶组件 React 高阶组件就是以高阶函数的方式包裹需要修饰的 React 组件,并返回处理...

  • React 进阶之高阶组件

    高阶组件 HOC 高阶组件(HOC)是react中的高级技术,用来重用组件逻辑。但高阶组件本身并不是React A...

  • 高阶组件

    React 高阶组件HOC (Higher-Order Component) 高阶组件是react中重复使用组件逻...

  • React高阶组件

    1、React高阶组件

  • React高阶组件HOC

    高阶组件本质是函数,参数是 组件1 返回组件2,高阶组件是为了复用通用逻辑高阶组件eg:import React,...

  • React高阶组件(HOC)

    高阶组件(Higher-Order Components) 高阶组件(HOC)是 React 中用于重用组件逻辑的...

  • react 笔记

    react 基本概念解析 react 的组件声明周期 react 高阶组件,context, redux 等高级...

  • ReactNative中的高阶组件(HOC)和继承详解

    ReactNative中的高阶组件(HOC)和继承详解 共同点: 高阶组件(HOC)是 React 中用于复用组件...

  • React高阶组件

    React高阶组件 在开始聊高阶组件之前我们先来看下高阶函数和高阶组件在形式上的差异: 一、什么是装饰器模式: 要...

  • React 高阶组件

    当 React 组件被包裹时(wrapped),高阶组件会返回一个增强(enhanced)的 React 组件。高...

网友评论

      本文标题:React高阶组件

      本文链接:https://www.haomeiwen.com/subject/tbmeyftx.html