React 代码复用模式的思考
文章目录

React 代码复用模式的思考

Mixin 模式

Mixin 模式的使用方法

Mixin 已经不推荐使用了, 详细的学习没有太大必要,了解一下即可。

  • 主要的实现就是通过 mixin 这个字段传进去一个额外的 object
  • 这个 object 并不是一个 class 但是可以使用生命周期方法
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
26
27
28
29
var LogMixin = {
log: function(v) {
console.log(v);
},
/* mixin 传进去的 class 甚至可以使用生命周期函数 */
// componentDidMount: function() {
// console.log('in');
// },
// componentWillUnmount: function() {
// console.log('out');
// }
};

var User = React.createClass({
mixins: [LogMixin],
componentDidMount: function() {
this.log(123456); // 我在这个地方就可以调用到 mixin 里面的那个方法。
},
render: function() {
return <div> ... < /div>;
},
});

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

Mixin 的缺点

  1. 非显式依赖
    • 很难获取对应的依赖树
  2. 命名冲突
    • 两个不同的 mixin 里面可能会有相同名称的函数,并且引用这个 mixin 的 class 里面可能也有一个相同的函数。
  3. 滚雪球式复杂性增加
    • Mixin 非常多时,组件是可以感知到的,甚至还要为其做相关处理

HOC

HOC 一般实现

1
2
3
4
5
6
7
8
9
10
function proxyHOC(WrappedComponent) {
return class extends Component {
render() {
return <WrappedComponent {
...this.props
}
/>;
}
}
}
  • 我们传进来一个 class,然后返回经过修饰之后的 class
  • 优势
    • 可以同时渲染多个组件, 可以对渲染进行条件控制
    • 可操作所有传入的 props
    • 可操作组件的生命周期
    • 可操作组件的 static 方法
    • 获取 refs

HOC 反向继承的实现

1
2
3
4
5
6
7
function inheritHOC(WrappedComponent) {
return class extends WrappedComponent {
render() {
return super.render();
}
}
}
  • 我们传进来一个 class, 然后返回继承这个 class 的 class
  • 优势
    • 可以同时渲染多个组件, 可以对渲染进行条件控制
    • 可操作所有传入的 props
    • 可操作组件的生命周期
    • 可操作组件的 static 方法
    • 获取 refs
    • 可操作 state(反向继承之后可以操作对应 class 的 state, 普通的 hoc 无法做到这一点)
    • 可以渲染劫持

如何使用 HOC

Compose

假设现在我们有 logger,visible,style 等多个 HOC,现在要同时增强一个 Input 组件:

1
logger(visible(style(Input)))

这种代码非常的难以阅读,我们可以手动封装一个简单的函数组合工具,将写法改写如下:

1
2
const compose = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
compose(logger,visible,style)(Input);

复制代码 compose 函数返回一个所有函数组合后的函数, compose(f, g, h)(...args) => f(g(h(...args))) 是一样的。

很多第三方库都提供了类似 compose 的函数,例如 lodash. flowRight,Redux 提供的 combineReducers 函数等。

ES7 Decorators

这种模式还没有标准化,所以需要配置一下才能使用

甚至这种模式可以和上方的 compose 结合使用: 其中 2 个 HOC 使用 compose, 另外 3 个用 Decorator 来装饰 (写成这个样子的人是多无聊啊!)

1
2
3
4
5
6
@logger
@visible
@style
class Input extends Component {
// ...
}

HOC 的实际应用场景

  • 日志 HOC
    • 这样子可以输出一个模块的 mount 以及 render 时间, 这个也很方便之后,之后来调查哪一个模块出了 bug
  • 输出控制及权限控制
    • 比如有时候未登录就不显示某一些插件
  • HOC 里面实现双向绑定
    • 其实就是在 hoc 里面写成 controller components, 然后对其做一系列的处理以及回调
    • 甚至也可以在里面进行表单校验

HOC 的缺点

大量嵌套, 调试困难

因为可以对 props 进行一些操作, 所以如果有大量嵌套的条件下,可能里面某一个环节对 props 进行了修改而导致后续出现问题

Hooks

Hooks 的优势

  1. 状态逻辑复用
  2. 避免嵌套地狱
  3. 组件理解起来更容易
  4. 方便使用函数代替 class

实际使用

(查看另一篇关于 React Hooks-Usage 的笔记)