基于Decorator的react组件扩展

@BoyuZhou 2016-08-30 00:39:20发表于 iuap-design/blog

基于Decorator的react组件扩展

react使用了ES2015语法之后,不支持mixin写法,但是可以通过decorator实现代码共享,使你的react程序变得更为可复用。

Decorator修饰器

修饰器(Decorator)是一个函数,用来修饰类的行为,在代码编译时,修改类的行为。
Decorator 可以通过返回特定的 descriptor 来”修饰” 类属性,也可以直接”修饰”一个类。即传入一个已有的类,通过 Decorator 函数”修饰”成了一个新的类。

function testable (target) {
target.isTestable = true;
}
@testable
class MyTestableClass {}

console.log(MyTestableClass.isTestable) //true

上面代码中@testable就是一个修饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。

使用Decorator对react组件进行扩展

import React from 'react';
import withViewport from 'react-decorators/withViewport';

@withViewport
class MyComponent {
  render() {
    let { width, height } = this.props.viewport;
    return <div>Viewport: {width + 'x' + height}</div>;
  }
}

React.render(<MyComponent />, document.body);

withView 是一个类增强函数,或者类修饰器,传入一个被扩展组件(MyComponent),返回一个新的组件。新组建具有获取窗口尺寸变化的能力(viewport),并且将viewport 通过 this.props.viewport 传递给被扩展组件(MyComponent)。

高阶组件

高阶组件就是复用高阶函数的思想,为基础组件增加新功能。Higher-Order Component = Decorator + Components.

import React, { Component } from 'React';

const PopupContainer = (Wrapper) =>
  class WrapperComponent extends Component {
    componentDidMount() {
      console.log('HOC did mount')
    }

    componentWillUnmount() {
      console.log('HOC will unmount')
    }

    render() {
      return <Wrapper {...this.props} />;
    }
  }

这个例子就是一个高阶组件,传入一个组件,再返回一个新的组件。要想使用这个组件,可以这样做。

import React, { Component } from 'React';

@PopupContainer
class MyComponent extends Component {
  render() {}
}

export default MyComponent;

PopupContainer就是一个修饰器,传入基本组件MyComponent,返回一个新的组件。

当然如果有很多个高阶组件,可以使用compose来简化修饰器调用

import React, { Component } from 'React';
import R from 'ramda';

const Decorators = R.compose(Decorator3(param), Decorator2,Decorator1);

class MyComponent extends Decorators(Component) {}

参考文档:
react mixin前世今生
基于Decorator的组件扩展实践
Higher-order Components 高阶组件