React组件逻辑复用的那些事儿

基本每个开发者都需要考虑逻辑复用的问题,否则你的项目中将充斥着大量的重复代码。那么 React 是怎么复用组件逻辑的呢?本文将一一介绍 React 复用组件逻辑的几种方法,希望你读完之后能够有所收获。如果你对这些内容已经非常清楚,那么略过本文即可。

我已尽量对文中的代码和内容进行了校验,但是因为自身知识水平限制,难免有错误,欢迎在评论区指正。

1. Mixins

Mixins 事实上是 React.createClass 的产物了。当然,如果你曾经在低版本的 react 中使用过 Mixins,例如 react-timer-mixinreact-addons-pure-render-mixin,那么你可能知道,在 React 的新版本中我们其实还是可以使用 mixin,虽然 React.createClass 已经被移除了,但是仍然可以使用第三方库 create-react-class,来继续使用 mixin。甚至,ES6 写法的组件,也同样有方式去使用 mixin。当然啦,这不是本文讨论的重点,就不多做介绍了,如果你维护的老项目在升级的过程中遇到这类问题,可以与我探讨。

新的项目中基本不会出现 Mixins,但是如果你们公司还有一些老项目要维护,其中可能就应用了 Mixins,因此稍微花点时间,了解下 Mixins 的使用方法和原理,还是有必要的。倘若你完全没有这方面的需求,那么跳过本节亦是可以的。

Mixins 的使用

React 15.3.0 版本中增加了 PureComponent。而在此之前,或者如果你使用的是 React.createClass 的方式创建组件,那么想要同样的功能,就是使用 react-addons-pure-render-mixin,例如:

//下面代码在新版React中可正常运行,因为现在已经无法使用 `React.createClass`,我就不使用 `React.createClass` 来写了。

const createReactClass = require('create-react-class');
const PureRenderMixin = require('react-addons-pure-render-mixin');

const MyDialog = createReactClass({
    displayName: 'MyDialog',
    mixins: [PureRenderMixin],
    //other code
    render() {
        return (
            <div>
                {/* other code */}
            </div>
        )
    }
});

首先,需要注意,mixins 的值是一个数组,如果有多个 Mixins,那么只需要依次放在数组中即可,例如: mixins: [PureRenderMixin, TimerMixin]

Mixins 的原理

Mixins 的原理可以简单理解为将一个 mixin 对象上的方法增加到组件上。类似于 $.extend 方法,不过 React 还进行了一些其它的处理,例如:除了生命周期函数外,不同的 mixins 中是不允许有相同的属性的,并且也不能和组件中的属性和方法同名,否则会抛出异常。另外即使是生命周期函数,constructorrendershouldComponentUpdate 也是不允许重复的。

而如 compoentDidMount 的生命周期,会依次调用 Mixins,然后再调用组件中定义的 compoentDidMount

例如,上面的 PureRenderMixin 提供的对象中,有一个 shouldComponentUpdate 方法,即是将这个方法增加到了 MyDialog 上,此时 MyDialog 中不能再定义 shouldComponentUpdate,否则会抛出异常。

//react-addons-pure-render-mixin 源码
var shallowEqual = require('fbjs/lib/shallowEqual');

module.exports = {
  shouldComponentUpdate: function(nextProps, nextState) {
    return (
      !shallowEqual(this.props, nextProps) ||
      !shallowEqual(this.state, nextState)
    );
  },
};
Mixins 的缺点
  1. Mixins 引入了隐式的依赖关系。

    例如,每个 mixin 依赖于其他的 mixin,那么修改其中一个就可能破坏另一个。

  2. Mixins 会导致名称冲突

    如果两个 mixin 中存在同名方法,就会抛出异常。另外,假设你引入了一个第三方的 mixin,该 mixin 上的方法和你组件的方法名发生冲突,你就不得不对方法进行重命名。

  3. Mixins 会导致越来越复杂

    mixin 开始的时候是简单的,但是随着时间的推移,容易变得越来越复杂。例如,一个组件需要一些状态来跟踪鼠标悬停,为了保持逻辑的可重用性,将 handleMouseEnter()handleMouseLeave()isHovering() 提取到 HoverMixin() 中。

    然后其他人可能需要实现一个提示框,他们不想复制 HoverMixin() 的逻辑,于是他们创建了一个使用 HoverMixinTooltipMixinTooltipMixin 在它的 componentDidUpdate 中读取 HoverMixin() 提供的 isHovering() 来决定显示或隐藏提示框。

    几个月之后,有人想将提示框的方向设置为可配置的。为了避免代码重复,他们将 getTooltipOptions() 方法增加到了 TooltipMixin 中。结果过了段时间,你需要在同一个组件中显示多个提示框,提示框不再是悬停时显示了,或者一些其他的功能,你需要解耦 HoverMixin()TooltipMixin 。另外,如果很多组件使用了某个 mixinmixin 中新增的功能都会被添加到所有组件中,事实上很多组件完全不需要这些新功能。

    渐渐地,封装的边界被侵蚀了,由于很难更改或移除现有的 mixin,它们变得越来越抽象,直到没有人理解它们是如何工作的。

React 官方认为在 React 代码库中,Mixin 是不必要的,也是有问题的。推荐开发者使用高阶组件来进行组件逻辑的复用。

2. HOC

React 官方文档对 HOC 进行了如下的定义:高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

简而言之,高阶组件就是一个函数,它接受一个组件为参数,返回一个新组件。

高阶组件形如下面这样:

//接受一个组件 WrappedComponent 作为参数,返回一个新组件 Proxy
function withXXX(WrappedComponent) {
    return class Proxy extends React.Component {
        render() {
            return <WrappedComponent {...this.props}>
        }
    }
}

开发项目时,当你发现不同的组件有相似的逻辑,或者发现自己在写重复代码的时候,这时候就需要考虑组件复用的问题了。

这里我以一个实际开发的例子来说明,近期各大APP都在适配暗黑模式,而暗黑模式下的背景色、字体颜色等等和正常模式肯定是不一样的。那么就需要监听暗黑模式开启关闭事件,每个UI组件都需要根据当前的模式来设置样式。

每个组件都去监听事件变化来 setState 肯定是不可能的,因为会造成多次渲染。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值