iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何使用React高阶组件解决横切关注点问题
  • 728
分享到

如何使用React高阶组件解决横切关注点问题

2023-07-04 17:07:20 728人浏览 泡泡鱼
摘要

这篇文章主要介绍“如何使用React高阶组件解决横切关注点问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何使用React高阶组件解决横切关注点问题”文章能帮助大家解决问题。高阶组件(HOC)概

这篇文章主要介绍“如何使用React高阶组件解决横切关注点问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何使用React高阶组件解决横切关注点问题”文章能帮助大家解决问题。

高阶组件(HOC)

概述

是React复用组件逻辑的一种高级技巧,是一种基于React组合特性而形成的设计模式

高阶组件是参数为组件,返回值为新组件的函数

简单理解:

  • 高阶组件本身是 函数,传参数是组件,返回值也是组件;

  • 高阶组件不用关心数据是如何渲染的,只用关心逻辑即可

  • 被包装的组件本身不用关心数据是怎么来的,只用负责渲染即可

  • 最后渲染的是高阶组件返回的组件

高阶组件的调用过程类似于这样:

const EnhancedComponent = higherOrderComponent(WrappedComponent);

应用场景:redux 中的 connect

使用HOC解决横切关注点问题

横切关注点问题:指的是一些具有横越多个模块的行为,使用传统的软件开发方法不能够达到有效的模块化的一类特殊关注点。

组件是React 中代码复用的基本单元,但某些模式并不适合传统组件

假设有一个 CommentList 组件,订阅外部数据源,用于渲染评论列表:

class CommentList extends React.Component {   constructor(props) {     super(props);     this.handleChange = this.handleChange.bind(this);     this.state = {       // 假设 "DataSource" 是个全局范围内的数据源变量,来自外部,自身带有很多方法       comments: DataSource.getComments()  //假设getComments()这个方法可以获取所有的评论     };   }   componentDidMount() {     // 订阅更改;监听  DataSource ,发生变化时更新数据     DataSource.addChangeListener(this.handleChange);   }   componentWillUnmount() {     // 清除订阅     DataSource.removeChangeListener(this.handleChange);   }   handleChange() {     // 当数据源更新时,更新组件状态     this.setState({       comments: DataSource.getComments()  //假设getComments()这个方法可以获取所有的评论     });   }   render() {     return (       <div>         {this.state.comments.map((comment) => (           <Comment comment={comment} key={comment.id} />         ))}       </div>     );   } } // 假设 DataSource:来自外部;它自身有很多方法,如:getComments(),addChangeListener,removeChangeListener 等//  假设 <Comment /> 是子组件,父组件 CommentList 需要将 comment 、key 传递给它

假设有个 订阅单个博客帖子的组件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 添加一个更改侦 听器在侦 听器

  • 内部,当数据源发生变化时,调用 setState

  • 在卸载时,删除侦 听器

上面两个组件相同点的地方被不断的重复调用,在大型项目中,所以我们需要将这些共同使用的地方给抽象出来,然后让许多组件之间共享它,这正是高阶组件擅长的地方。

编写一个创建组件函数,这个函数接收两个参数,一个是要被包装的子组件,另一个则是该子组件订阅数据的函数。

 const CommentListWithSubscription = withSubscription(    CommentList,    (DataSource) => DataSource.getComments()  );  const BlogPostWithSubscription = withSubscription(    BlogPost,    (DataSource, props) => DataSource.getBlogPost(props.id)  );//以上写法相当于高级组件的调用,withSubscription为自定义的高阶组件;CommentList:被包装的子组件;CommentListWithSubscription:返回的包装后的组件

当渲染 CommentListWithSubscription 和 BlogPostWithSubscription 时, CommentList 和 BlogPost 将传递一个 data prop,其中包含从 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() {     // ... 并使用新数据渲染被包装的组件!     // 请注意,我们可能还会传递其他属性     return <WrappedComponent data={this.state.data} {...this.props} />;   } };}

HOC不会修改传入的组件,也不会使用继承来复制其行为,相反HOC是通过将组件包装在容器组件中来组成新的组件,HOC是纯函数,没有副作用

  • 被包装组件接收来自容器组件的所有prop,同时也接收一个新的用于render的data prop

  • HOC不用关心数据的使用方式,被包装组件也不用关心数据是怎么来的

不用改变原始组件使用组合

不要试图在 HOC 中修改组件原型(或以其他方式改变它)

function logProps(InputComponent) { InputComponent.prototype.componentDidUpdate = function(prevProps) {   console.log('Current props: ', this.props);   console.log('Previous props: ', prevProps); }; // 返回原始的 input 组件,暗示它已经被修改。 return InputComponent;}// 每次调用 logProps 时,增强组件都会有 log 输出。const EnhancedComponent = logProps(InputComponent)//上面这种写法会造成另一个同样会修改componentDidUpate的HOC增强它,那么前面的HOC就会失效。

HOC不应该修改传入组件,而应该使用组合的方式,将组件包装在容器组件中实现功能。

function logProps(WrappedComponent) {    return class extends React.Component {      componentDidUpdate(prevProps) {        console.log('Current props: ', this.props);        console.log('Previous props: ', prevProps);      }      render() {        // 将 input 组件包装在容器中,而不对其进行修改。Good!        return <WrappedComponent {...this.props} />;      }    }  }

约定-将不相关的 props 传递给被包裹的组件

HOC为组件添加特性,自身不应该大幅改变约定,HOC应该透传与自身无关的props,大多数HOC都应该包含一个类似于下面的render方法

render() {  // 过滤掉非此 HOC 额外的 props,且不要进行透传  const { extraProp, ...passThroughProps } = this.props;  // 将 props 注入到被包装的组件中。  // 通常为 state 的值或者实例方法。  const injectedProp = someStateOrInstanceMethod;  // 将 props 传递给被包装组件  return (    <WrappedComponent      injectedProp={injectedProp}      {...passThroughProps}    />  );}

约定-最大化可组合性

有时候它仅接受一个参数,也就是被包裹的组件:

const NavbarWithRouter = withRouter(Navbar);

HOC通常也可以接收多个参数

const CommentWithRelay = Relay.createContainer(Comment, config);

常见的HOC签名(React Redux的connect函数):

// React Redux 的 `connect` 函数const ConnectedComment = connect(commentSelector, commentActions)(CommentList);

拆分connect函数

  // connect 是一个函数,它的返回值为另外一个函数。  const enhance = connect(commentListSelector, commentListActions)  // 返回值为 HOC,它会返回已经连接 Redux store 的组件 const ConnectedComment = enhance(CommentList);

约定-包装显示名称以便轻松调试

HOC创建的容器组件会和任何其他组件一样,显示在React Developer Tools中,为了方便调试,需要选择显示一个名称,以表明他是HOC的产物

function withSubscription(WrappedComponent) { class WithSubscription extends React.Component {} WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`; return WithSubscription;}function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component';}

使用高阶组件的注意事项

不要在render方法中使用HOC

render() {  // 每次调用 render 函数都会创建一个新的 EnhancedComponent  // EnhancedComponent1 !== EnhancedComponent2  const EnhancedComponent = enhance(MyComponent);  // 这将导致子树每次渲染都会进行卸载,和重新挂载的操作!  return <EnhancedComponent />;}

务必复制静态方法

   // 定义静态函数 WrappedComponent.staticMethod = function() {} // 现在使用 HOC const EnhancedComponent = enhance(WrappedComponent); // 增强组件没有 staticMethod typeof EnhancedComponent.staticMethod === 'undefined' // true//为了解决这个问题,你可以在返回之前把这些方法拷贝到容器组件上:function enhance(WrappedComponent) {   class Enhance extends React.Component {}   // 必须准确知道应该拷贝哪些方法 :(   Enhance.staticMethod = WrappedComponent.staticMethod;   return Enhance }

Refs 不会被传递

虽然高阶组件的约定是将所有 props 传递给被包装组件,但这对于 refs 并不适用。那是因为 ref 实际上并不是一个 prop - 就像 key 一样,它是由 React 专门处理的。如果将 ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件。

关于“如何使用React高阶组件解决横切关注点问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: 如何使用React高阶组件解决横切关注点问题

本文链接: https://www.lsjlt.com/news/346601.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何使用React高阶组件解决横切关注点问题
    这篇文章主要介绍“如何使用React高阶组件解决横切关注点问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何使用React高阶组件解决横切关注点问题”文章能帮助大家解决问题。高阶组件(HOC)概...
    99+
    2023-07-04
  • 如何解决React中组件通信问题
    这篇文章将为大家详细讲解有关如何解决React中组件通信问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。父子组件父 → 子parent组件传给child组件,符合rea...
    99+
    2024-04-02
  • React如何使用高阶组件与Hooks实现权限拦截
    本篇内容主要讲解“React如何使用高阶组件与Hooks实现权限拦截”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React如何使用高阶组件与Hooks实现权限拦截”吧!高阶组件是以组件作为参数...
    99+
    2023-07-05
  • 如何解决vue组件路由高亮的问题
    这篇文章给大家分享的是有关如何解决vue组件路由高亮的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框架的区别是,使用...
    99+
    2023-06-15
  • 如何解决React使用browserHistory项目访问404的问题
    这篇文章主要介绍了如何解决React使用browserHistory项目访问404的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。最近项...
    99+
    2024-04-02
  • 如何解决semantic-ui-react图像组件不显示图像的问题
    这篇文章主要介绍了如何解决semantic-ui-react图像组件不显示图像的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。问题Rea...
    99+
    2024-04-02
  • 如何解决@Table注解无法使用的问题
    这篇文章主要介绍了如何解决@Table注解无法使用的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。@Table注解无法使用及报红在新建实体类时想直接序列化,遇到注解不起作...
    99+
    2023-06-26
  • 如何解决vue组件中使用v-for出现告警问题
    这篇文章给大家分享的是有关如何解决vue组件中使用v-for出现告警问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在项目中运行v-for代码段时,<flexbox&nb...
    99+
    2024-04-02
  • 如何解决cpu使用率忽高忽低的问题
    小编给大家分享一下如何解决cpu使用率忽高忽低的问题,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!首先要明白在哪里查看CPU使用率,鼠标右键点击桌面的底部工具栏,然后选择启动任务管理器。在弹出的Windows任务管理器选项...
    99+
    2023-06-28
  • C语言中如何使用递归解决青蛙跳台阶问题
    这篇文章主要介绍C语言中如何使用递归解决青蛙跳台阶问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、求解思路台阶的数量为n。当 n = 1 时,青蛙有一种跳法,即跳1级台阶。当 n = 2 时,青蛙有两种跳法,即...
    99+
    2023-06-25
  • jpa使用注解生成表时无外键问题如何解决
    这篇“jpa使用注解生成表时无外键问题如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“jpa使用注解生成表时无外键问题...
    99+
    2023-07-02
  • Python 面试中的数组问题:如何使用 NumPy 解决?
    在 Python 面试中,往往会遇到一些与数组相关的问题,例如如何求一个数组的平均值、中位数、最大值、最小值等等。这些问题在实际开发中也是经常遇到的,因此我们需要掌握一些数组操作的技巧。 在 Python 中,有一个非常强大的数组库,叫做...
    99+
    2023-08-30
    面试 数组 numy
  • 如何在LeetCode上使用Go语言解决数组问题?
    LeetCode是一个非常受欢迎的在线编程平台,它提供了大量的算法题目和数据结构问题,帮助程序员提高自己的编程技能。而Go语言是一种非常流行的编程语言,具有高效、简洁、安全等优点。在本文中,我们将介绍如何在LeetCode上使用Go语言解决...
    99+
    2023-11-14
    http leetcode 数组
  • vue如何使用axios时解决关于this指向的问题
    这篇文章将为大家详细讲解有关vue如何使用axios时解决关于this指向的问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.解决办法在vue中使用axios做网络请...
    99+
    2024-04-02
  • Win7如何手动注册DLL文件以解决程序不能使用的问题
      我们在使用Win7系统的时候,常常用到一些程序,会说需要重新注册一些程序相关的XXX.DLL文件,只有注册过后程序才能正常使用,那么我们该如何手动注册DLL文件呢   Win7手动注册DLL文件方法:   在运行中输...
    99+
    2023-06-11
    Win7 DLL文件 程序 问题
  • react的ui库antd中form表单使用SelectTree反显问题如何解决
    这篇文章主要介绍了react的ui库antd中form表单使用SelectTree反显问题如何解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇react的ui库antd中form表单使用SelectTree反...
    99+
    2023-07-05
  • 如何解决使用vue-aplayer插件时出现的问题
    这篇文章主要介绍如何解决使用vue-aplayer插件时出现的问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:安装$ npm install ...
    99+
    2024-04-02
  • 如何解决python 使用openpyxl读写大文件的问题
    这篇文章主要讲解了“如何解决python 使用openpyxl读写大文件的问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何解决python 使用openpyxl读写大文件的问题”吧!由...
    99+
    2023-06-14
  • 如何使用vbs解决处理TXT文本数据相关问题
    这篇文章主要介绍了如何使用vbs解决处理TXT文本数据相关问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。有个小问题,如下: 现有文本文件1.txt,内容如下: 数值_1出...
    99+
    2023-06-08
  • vue中如何解决使用element组件时事件想要传递其他参数的问题
    小编给大家分享一下vue中如何解决使用element组件时事件想要传递其他参数的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作