首页 web前端 js教程 React高阶组件实例解析

React高阶组件实例解析

May 26, 2018 am 11:51 AM
react 实例 解析

本文主要带大家深入理解React高阶组件,希望大家对React高阶组件有一个更清晰的认识。

1.在React中higher-order component (HOC)是一种重用组件逻辑的高级技术。HOC不是React API中的一部分。HOC是一个函数,该函数接收一个组件并且返回一个新组件。在React中,组件是代码复用的基本单位。

2.为了解释HOCs,举下面两个例子

CommentList组件会渲染出一个comments列表,列表中的数据来自于外部。

class CommentList extends React.Component {

  constructor() {

   super();

   this.handleChange = this.handleChange.bind(this);

   this.state = {

    // "DataSource" is some global data source

    comments: DataSource.getComments()

   };

  }

 

  componentDidMount() {

   // Subscribe to changes

   DataSource.addChangeListener(this.handleChange);

  }

 

  componentWillUnmount() {

   // Clean up listener

   DataSource.removeChangeListener(this.handleChange);

  }

 

  handleChange() {

   // Update component state whenever the data source changes

   this.setState({

    comments: DataSource.getComments()

   });

  }

 

  render() {

   return (

    <p>

     {this.state.comments.map((comment) => (

      <Comment comment={comment} key={comment.id} />

     ))}

    </p>

   );

  }

 }
登录后复制

接下来是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的不同方法,并且它们的输出也不一样,但是它们中的大部分实现是一样的:

1.装载完成后,给DataSource添加了一个change listener
2.当数据源发生变化后,在监听器内部调用setState
3.卸载之后,移除change listener

可以想象在大型应用中,相同模式的访问DataSource和调用setState会一次又一次的发生。我们希望抽象这个过程,从而让我们只在一个地方定义这个逻辑,然后在多个组件中共享。

接下来我们写一个创建组件的函数,这个函数接受两个参数,其中一个参数是组件,另一个参数是函数。下面调用withSubscription函数

const CommentListWithSubscription = withSubscription(

 CommentList,

 (DataSource) => DataSource.getComments()

);

 

const BlogPostWithSubscription = withSubscription(

 BlogPost,

 (DataSource, props) => DataSource.getBlogPost(props.id)

);
登录后复制

调用withSubscription传的第一个参数是wrapped 组件,第二个参数是一个函数,该函数用于检索数据。

当CommentListWithSubscription和BlogPostWithSubscription被渲染,CommentList和BlogPost会接受一个叫做data的prop,data中保存了当前从DataSource中检索出的数据。withSubscription代码如下:

// This function takes a component...

function withSubscription(WrappedComponent, selectData) {

 // ...and returns another component...

 return class extends React.Component {

  constructor(props) {

   super(props);

   this.handleChange = this.handleChange.bind(this);

   this.state = {

    data: selectData(DataSource, props)

   };

  }

 

  componentDidMount() {

   // ... that takes care of the subscription...

   DataSource.addChangeListener(this.handleChange);

  }

 

  componentWillUnmount() {

   DataSource.removeChangeListener(this.handleChange);

  }

 

  handleChange() {

   this.setState({

    data: selectData(DataSource, this.props)

   });

  }

 

  render() {

   // ... and renders the wrapped component with the fresh data!

   // Notice that we pass through any additional props

   return <WrappedComponent data={this.state.data} {...this.props} />;

  }

 };

}
登录后复制

HOC并没有修改输入的组件,也没有使用继承去重用它的行为。HOC只是一个函数。wrapped 组件接受了容器的所以props,同时还接受了一个新的prop(data),data用于渲染wrapped 组件的输出。HOC不关心数据怎么使用也不关心数据为什么使用,wrapped组件不关心数据是哪儿得到。

因为withSubscription只是一个常规的函数,你能添加任意个数的参数。例如,你能让data prop的名字是可配置的,从而进一步将HOC与wrapped组件隔离。

或者接受一个配置shouldComponentUpdate,或者配置数据源的参数

使用高阶组件时有些需要注意的地方。

1.不要修改原始组件,这一点很重要

有如下例子:

function logProps(InputComponent) {

 InputComponent.prototype.componentWillReceiveProps = function(nextProps) {

  console.log(&#39;Current props: &#39;, this.props);

  console.log(&#39;Next props: &#39;, nextProps);

 };

 // The fact that we&#39;re returning the original input is a hint that it has

 // been mutated.

 return InputComponent;

}

 

// EnhancedComponent will log whenever props are received

const EnhancedComponent = logProps(InputComponent);
登录后复制

这里存在一些问题,1.输入的组件不能与增强的组件单独重用。2.如果给EnhancedComponent应用其他的HOC,也会改变componentWillReceiveProps。

这个HOC对函数类型的组件不适用,因为函数类型组件没有生命周期函数HOC应该使用合成代替修改——通过将输入的组件包裹到容器组件中。

function logProps(WrappedComponent) {

 return class extends React.Component {

  componentWillReceiveProps(nextProps) {

   console.log(&#39;Current props: &#39;, this.props);

   console.log(&#39;Next props: &#39;, nextProps);

  }

  render() {

   // Wraps the input component in a container, without mutating it. Good!

   return <WrappedComponent {...this.props} />;

  }

 }

}
登录后复制

这个新的logProps与旧的logProps有相同的功能,同时新的logProps避免了潜在的冲突。对class类型的组件和函数类型额组件同样适用。

2.不要在render方法中使用HOCs

React的diff算法使用组件的身份去决定是应该更新已存在的子树还是拆除旧的子树并装载一个新的,如果从render方法中返回的组件与之前渲染的组件恒等(===),那么React会通过diff算法更新之前渲染的组件,如果不相等,之前渲染的子树会完全卸载。

render() {

 // A new version of EnhancedComponent is created on every render

 // EnhancedComponent1 !== EnhancedComponent2

 const EnhancedComponent = enhance(MyComponent);

 // That causes the entire subtree to unmount/remount each time!

 return <EnhancedComponent />;

}
登录后复制

在组件定义的外部使用HOCs,以至于结果组件只被创建一次。在少数情况下,你需要动态的应用HOCs,你该在生命周期函数或者构造函数中做这件事

3.静态方法必须手动复制

有的时候在React组件上定义静态方法是非常有用的。当你给某个组件应用HOCs,虽然原始组件被包裹在容器组件里,但是返回的新组件不会有任何原始组件的静态方法。

// Define a static method

WrappedComponent.staticMethod = function() {/*...*/}

// Now apply an HOC

const EnhancedComponent = enhance(WrappedComponent);

 

// The enhanced component has no static method

typeof EnhancedComponent.staticMethod === &#39;undefined&#39; // true
登录后复制

为了让返回的组件有原始组件的静态方法,就要在函数内部将原始组件的静态方法复制给新的组件。


function enhance(WrappedComponent) {

 class Enhance extends React.Component {/*...*/}

 // Must know exactly which method(s) to copy :(

  // 你也能够借助第三方工具

 Enhance.staticMethod = WrappedComponent.staticMethod;

 return Enhance;

}
登录后复制

 4.容器组件上的ref不会传递给wrapped component

虽然容器组件上的props可以很简单的传递给wrapped component,但是容器组件上的ref不会传递到wrapped component。如果你给通过HOCs返回的组件设置了ref,这个ref引用的是最外层容器组件,而非wrapped 组件。

相关推荐

React 高阶组件入门实例分享

Vue高阶组件的使用方法

用很简单的实例理解react.js高阶组件思想

以上是React高阶组件实例解析的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP 中点的含义和用法解析 PHP 中点的含义和用法解析 Mar 27, 2024 pm 08:57 PM

【PHP中点的含义和用法解析】在PHP中,中点(.)是一个常用的操作符,用于连接两个字符串或者对象的属性或方法。在本文中,我们将深入探讨PHP中点的含义和用法,并通过具体的代码示例加以说明。1.连接字符串中点操作符.在PHP中最常见的用法是连接两个字符串。通过将.放置在两个字符串之间,可以将它们拼接在一起,形成一个新的字符串。$string1=&qu

Java框架与前端React框架的整合 Java框架与前端React框架的整合 Jun 01, 2024 pm 03:16 PM

Java框架与React框架的整合:步骤:设置后端Java框架。创建项目结构。配置构建工具。创建React应用。编写RESTAPI端点。配置通信机制。实战案例(SpringBoot+React):Java代码:定义RESTfulAPI控制器。React代码:获取并显示API返回的数据。

Win11新功能解析:跳过登录微软账户的方法 Win11新功能解析:跳过登录微软账户的方法 Mar 27, 2024 pm 05:24 PM

Win11新功能解析:跳过登录微软账户的方法随着Windows11的发布,许多用户发现其带来了更多的便捷和新功能。然而,有些用户可能不喜欢将其系统与微软账户绑定,希望跳过这一步骤。本文将介绍一些方法,帮助用户在Windows11中跳过登录微软账户,实现更加私密和自主的使用体验。首先,我们来了解一下为什么有些用户不愿意登录微软账户。一方面,一些用户担心他们

vue.js vs.反应:特定于项目的考虑因素 vue.js vs.反应:特定于项目的考虑因素 Apr 09, 2025 am 12:01 AM

Vue.js适合中小型项目和快速迭代,React适用于大型复杂应用。1)Vue.js易于上手,适用于团队经验不足或项目规模较小的情况。2)React的生态系统更丰富,适合有高性能需求和复杂功能需求的项目。

React在HTML中的作用:增强用户体验 React在HTML中的作用:增强用户体验 Apr 09, 2025 am 12:11 AM

React通过JSX与HTML结合,提升用户体验。1)JSX嵌入HTML,使开发更直观。2)虚拟DOM机制优化性能,减少DOM操作。3)组件化管理UI,提高可维护性。4)状态管理和事件处理增强交互性。

反应与前端:建立互动体验 反应与前端:建立互动体验 Apr 11, 2025 am 12:02 AM

React是构建交互式前端体验的首选工具。1)React通过组件化和虚拟DOM简化UI开发。2)组件分为函数组件和类组件,函数组件更简洁,类组件提供更多生命周期方法。3)React的工作原理依赖虚拟DOM和调和算法,提高性能。4)状态管理使用useState或this.state,生命周期方法如componentDidMount用于特定逻辑。5)基本用法包括创建组件和管理状态,高级用法涉及自定义钩子和性能优化。6)常见错误包括状态更新不当和性能问题,调试技巧包括使用ReactDevTools和优

C语言中的基本单位解析 C语言中的基本单位解析 Mar 23, 2024 pm 05:06 PM

C语言中的基本单位解析在学习C语言时,了解C语言中的基本单位是非常重要的。C语言中的基本单位包括字符、整数、浮点数和数组等。本文将分别解析这些基本单位,并附上具体的代码示例。一、字符在C语言中,字符是基本的数据类型之一。字符在C语言中是以ASCII码的形式存储的,每个字符对应一个ASCII码。我们可以使用单引号来表示一个字符。下面是一个示例代码,展示了如何声

React与Vue:Netflix使用哪个框架? React与Vue:Netflix使用哪个框架? Apr 14, 2025 am 12:19 AM

NetflixusesAcustomFrameworkcalled“ Gibbon” BuiltonReact,notReactorVueDirectly.1)TeamExperience:selectBasedAsedonFamiliarity.2)ProjectComplexity:vueforsimplerprojects,vueforsimplerprojects,reactforforforecomplexones.3)cocatizationNeedsneeds:reactofficatizationneedneeds:reactofferizationneedneedneedneeds:reactoffersizatization needeffersefersmoreflexiblesimore.4)ecosyaka

See all articles