资讯专栏INFORMATION COLUMN

React中的函数子组件(FaCC)和高阶组件(HOC)

elliott_hu / 1246人阅读

摘要:高阶函数我们都用过,就是接受一个函数然后返回一个经过封装的函数而高阶组件就是高阶函数的概念应用到高阶组件上使用接受一个组件返回一个经过包装的新组件。灵活性在组合阶段相对更为灵活,他并不规定被增强组件如何使用它传递下去的属性。

在接触过React项目后,大多数人都应该已经了解过或则用过了HOC(High-Order-Components)和FaCC(Functions as Child Components),因为这两个模式在大多数react的开源库里都存在。比如react-router里面的withRouter 就是典型的高阶组件,接受一个组件返回另外一个经过增强后的组件。而react-motion中的Motion就是典型的FaCC的应用。

HOC和FaCC两者做的事也是非常相似的,都是类似设计模式里面的装饰者模式。都是在原有的实例或则单元上进行功能的增强。

当然不只是一些开源库中会使用,在平常的代码编写中,也有很多地方是适用于使用HOC和FaCC去封装一些逻辑。比如数据埋点,新特性的toggle,获取转换数据等。对于增强代码可读性和逻辑复用来说,非常有用的。

HOC

高阶函数我们都用过,就是接受一个函数然后返回一个经过封装的函数:

const plus = first => second => (first + second)
plus(1)(2) // 3

而高阶组件就是高阶函数的概念应用到高阶组件上:

const withClassName = ComposedComponent => props => (
   
)

// 使用
const Header = text => (
{text}
) const headerWitheClass = withClassName(Header)

接受一个组件返回一个经过包装的新组件。在我们经常使用的withRouter就是在原有组件props上面在加上localtion等属性。除了添加props以外高阶组件还能做到:

在真正调用组件前后做一些事,比如埋点数据等

判断组件是否该render,或则应该render其他的东西,比如出错之后render错误页面

传递props并增加新的props

不render组件,转而做一些其他的事情,比如渲染一个外部的dom

对于上面的前三点都比较好理解,解释一下第4点。比如你在render了一个页面之后,需要改变一下页面的title.这是单页应用普遍存在的一个需求,通常你可以在具体router库中使用hook去实现。当然也可以通过HOC来实现:

const withTitleChange = ComposedComponent => {
  return class extends React.Component {
    componentDidMount () {
      const { title } = this.props
      document.title = title
    }
    render () {
      const props = this.props
      return 
    }
  }
}
FaCC

同样FaCC也是用于增强原有组件能力的一种模式,其主要功能的实现在于react的props.children可以是任何东西,包括函数。我们可以拿上面class的例子用FaCC再实现一遍:

const ClassNameWrapper = ({ children }) => children("demo-class")

// 使用

const HeadWithClass = (props) => (
  
    {(class) => 
}
)

在FaCC中你也可以像HOC一样在生命周期中做很多事对原有的组件进行封装,基本上HOC能做的FaCC也都能做。我所在的项目之前都是大范围的使用HOC,再经过一番讨论后,开始大范围的转变成FaCC。

区别

两者都是用来增强原有组件的,具体该使用那种?那种是正确的模式?社区关于这一点也有很多讨论,比如就有人说FaCC是反模式:Function as Child Components Are an Anti-Pattern。他给出的理由是children并不语义化,会造成困惑,然后他提出了Component Injection的模式,有兴趣的同学可以读一读。

具体从几个方面做一下对比:

组合阶段

组合阶段意思就是HOC,FaCC和要被增强的组件的组合时候。可以很明显发现,FaCC对于前后组件对接依赖信息显示的更多,相对而言更容易理解。而HOC,相互之间如何桥接,你必须得深入到HOC内部读代码才可以知道这个HOC具体干了啥。

// HOC example
import View from "./View"

const DetailPage = withServerData(withNavigator(View))
// FaCC example

import View from "./View"

const DetailPage = props => (
  
    {
      data => (
        
          
        
      )
    }
  
)

如果在上面再增加2个HOC,上面组合的过程就变得十分难看。而FaCC相对而言,如何封装,数据源来自那里,组件接受了那些数据都比较显眼。

性能优化

在HOC中我们能接受到宿主的prop,因为props是从HOC往下传递的,所以我们也有完整的生命周期,我们可以使用shouldComponentUpdate优化。而FaCC则不然,无法在其内部做比较props,除非在组合的时候外部在包一个组件才能进行比较props。

灵活性

FaCC 在组合阶段相对HOC更为灵活,他并不规定被增强组件如何使用它传递下去的属性。而HOC基本上在编写完后就定死了。

另外,FaCC不会再去创建一个新的Component,而HOC会创建一个新的Component然后传递props下去。

总结

社区中很多开源库已经使用了两种模式,也有很多的文章进行比较。也有很多激烈讨论,当然对于最后解决问题而言,两种模式都有好处。出于不同的考虑,可能选择不一样。

参考文章:

http://rea.tech/functions-as-...

http://rea.tech/reactjs-real-...

https://medium.com/merrickchr...

http://www.ituring.com.cn/boo... 第四章

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97387.html

相关文章

  • [源码解读] react-redux

    摘要:本文并不逐行地对源码进行细致分析,不如说是基于以下几个问题,对源码进行大致的扫览。我们已经知道,中,允许用户注册监听器,这些监听器会在每次执行结束后遍历触发。省略一些无关代码其中,是为了在嵌套的中嵌套执行。 react-redux 源码解读 [TOC] 前置知识 阅读本篇文章前,请先确认你是否了解以下知识: react redux 高阶组件 react diff 机制 其中高阶组件...

    Olivia 评论0 收藏0
  • 使用Vue的HOC技术开发一个无限加载列表

    摘要:高阶组件的概念,是里面经常提到的,类似于高阶函数。高阶函数高阶组件高阶组件用是代码复用的优秀工具,主要在处理逻辑方面和普适性上,有着奇效。 前言 在web开发上,我们都对数据采用分页加载的机制,一种变形就是在页面采用循环加载的机制,拉到页面最下方有个加载更多的按钮。问题在于,当不同的数据要展示时,就要写很多这种列表,但是其中的逻辑都是相似的。 维护一组数据 加载更多数据 将数据用对应...

    stefan 评论0 收藏0
  • 装饰者模式的应用:react高阶组件ES6 装饰器

    摘要:装饰者模式参与者装饰者和被装饰者共同的父类,是一个接口或者抽象类,用来定义基本行为定义具体对象,即被装饰者抽象装饰者,继承自,从外类来扩展。三装饰器高阶组件可以看做是装饰器模式在的实现。 一 装饰者模式 优先使用对象组合而不是类继承。 --《设计模式》 1.什么是装饰者模式 定义:动态的给对象添加一些额外的属性或行为。相比于使用继承,装饰者模式更加灵活。 2.装饰者模式参与者 Co...

    YuboonaZhang 评论0 收藏0
  • React系列之一起认识Render Prop

    摘要:比如有个组件,它用来实时的获取鼠标的位置。命名空间,多个修改同一个导致的命名冲突。据说源码里面为每个组件增加路由属性就是通过该方法好了大功完成了,欢迎一起讨论学习个人博客地址意卿 1.mixins 写过react项目的应该都碰到过,不同组件复用相同代码的问题,在react早期使用React.createClass创建组件的时代,我们经常使用的是mixins来实现代码复用。比如有个组件A...

    LMou 评论0 收藏0
  • 从Preact了解一个类React的框架是怎么实现的(三): 组件

    摘要:组件渲染首先我们来了解组件返回的虚拟是怎么渲染为真实,来看一下的组件是如何构造的可能我们会想当然地认为组件的构造函数定义将会及其复杂,事实上恰恰相反,的组件定义代码极少。 前言   首先欢迎大家关注我的掘金账号和Github博客,也算是对我的一点鼓励,毕竟写东西没法获得变现,能坚持下去也是靠的是自己的热情和大家的鼓励。  之前分享过几篇关于React的文章: React技术内幕: k...

    AlphaWatch 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<