react中的mixins、hoc、hooks三者对比

react的高阶组件浅析
react中Hooks浅析
react的mixins、hoc、hooks对比

简介

Mixin(混入)是一种通过扩展收集功能的方式,它本质上是将一个对象的属性拷贝到另一个对象上面去,不过你可以拷贝任意多个对象的任意个方法到一个新对象上去,这是继承所不能实现的。它的出现主要就是为了解决代码复用问题
如下图所示:
reac-mixins
Mixin是用来提取可复用的逻辑或者方法,并且它比继承要更令活,它的应用范围也是比较广的比如在JQueryextend方法。

Mixin大致实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function setMixin(target, mixin) {
if (arguments[2]) {
for (var i = 2, len = arguments.length; i < len; i++) {
t arget.prototype[arguments[i]] = mixin.prototype[arguments[i]];
}
}
else {
for (var methodName in mixin.prototype) {
if (!Object.hasOwnProperty(target.prototype, methodName)) {
target.prototype[methodName] = mixin.prototype[methodName];
}
}
}
}
setMixin(User,LogMixin,'actionLog');
setMixin(Goods,LogMixin,'requestLog');

您可以使用setMixin方法将任意对象的任意方法扩展到目标对象上。

React中的Mixin

React也提供了Mixin的实现,如果完全不同的组件有相似的功能,我们可以引入来实现代码复用,当然只有在使用createClass来创建React组件时才可以使用,因为在React组件的es6写法中它已经被废弃掉了。

例如下面的例子,很多组件或页面都需要记录用户行为,性能指标等。如果我们在每个组件都引入写日志的逻辑,会产生大量重复代码,通过Mixin我们可以解决这一问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var LogMixin = {
log: function () {
console.log('log');
},
componentDidMount () {
console.log('in');
},
componentWillUnmount () {
console.log('out');
}
};

var User = React.createClass({
mixins: [LogMixin],
render () {
return (<div></div>);
}
});

var Goods = React.createClass({
mixins: [LogMixin],
render () {
return (<div></div>);
}
});

Mixin的缺陷

React官方文档在Mixins Considered Harmful一文中提到了Mixin带来了危害:

  • Mixin 可能会相互依赖,相互耦合,不利于代码维护
  • 不同的Mixin中的方法可能会相互冲突
  • Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性

React现在已经不再推荐使用Mixin来解决代码复用问题,因为Mixin带来的危害比他产生的价值还要巨大,并且React全面推荐使用高阶组件来替代它。

高阶组件

React推荐高阶组件和代替Mixin来做逻辑、代码复用,这里就不多赘述Hoc的使用和作用,如果不太清楚的可以看另一篇博客来了解React中的HOC,react的高阶组件浅析

HOC的作用

HOC可以比Mixin做更多的事情,也没有Mixin产生那么大副作用,具体实现什么样的功能如下:

  • 操作 props(属性)(通过属性代理实现、通过反向继承实现)
  • 通过 Refs 访问到组件实例 (通过属性代理实现)
  • 组件状态提升(通过属性代理实现)
  • 操作state (通过反向继承实现)
  • 渲染劫持(通过属性代理实现、通过反向继承实现)
  • 用其他元素包裹 WrappedComponent (通过属性代理实现)

HOC的缺陷

  • HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难。
  • HOC可以劫持props,在不遵守约定的情况下也可能造成冲突。

在新版的React中推行Hooks来替代HOC。它可以同时解决Mixin和HOC带来的问题

Hooks

React v16.7.0-alpha中加入了新的特性Hooks,他可以让你在class以外使用state和其他React特性。

使用Hooks,你可以在将含有state的逻辑从组件中抽象出来,这将可以让这些逻辑容易被测试。同时,Hooks可以帮助你在不重写组件结构的情况下复用这些逻辑。所以,它也可以作为一种实现状态逻辑复用的方案

可以看另一篇博客react中Hooks浅析

hook使用事项

Hook 本质就是 JavaScript 函数,但是在使用它时需要遵循两条规则。

只在最顶层使用 Hook

不要循环,条件或嵌套函数调用 Hook, 确保总是在你的 React 函数的最顶层调用他们。

使用范围

不要普通的 JavaScript 函数中调用 Hook。只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。
Hook的提出主要就是为了解决class组件的一系列问题,所以我们能在class组件中使用它

总结

程序的发展提出一个可以解决当前问题的方案,但随着时间的变化发现以前的方案有很大的副作用或者有更好的方案,就会更新一套更好的方案来解决问题,就像React中复用逻辑的变化从Mixin(已废弃)到HOC(用的比较多)再到现在的Hooks(新贵),可能以后Hooks也会落伍但是一定要保持学习。

参考

【React深入】从Mixin到HOC再到Hook
react的高阶组件浅析
react中Hooks浅析