amenzai / myDiary

Record what you do every day
4 stars 0 forks source link

react 小册记录 #81

Open amenzai opened 5 years ago

amenzai commented 5 years ago

1、

const ControlButtons = (props) => {
  //TODO: 返回两个按钮的JSX
};

ControlButtons.propTypes = {
  activated: PropTypes.bool,
  onStart: PropTypes.func.isRquired,
  onPause: PropTypes.func.isRquired,
  onSplit: PropTypes.func.isRquired,
  onReset: PropTypes.func.isRquired,
  splits: PropTypes.arrayOf(PropTypes.number)
};
super(...arguments);
state = {
    isStarted: false,
    startTime: null,
    currentTime: null,
    splits: [],
  }
onPause = () => {
    clearInterval(this.intervalHandle);
    this.setState({
      isStarted: false,
    });
  }
amenzai commented 5 years ago

[建议]高阶组件返回新的组件类型时,添加displayName属性。

同时在displayName上声明高阶组件的存在。

// Good
let asPureComponent = Component => {
    let componentName = Component.displayName || Component.name || 'UnknownComponent';
    return class extends PureComponent {
        static displayName = `asPure(${componentName})`

        render() {
            return <Component {...this.props} />;
        }
    };
};
amenzai commented 5 years ago

[建议]使用@autobind进行事件处理方法与this的绑定。

由于PureComponent使用shallowEqual进行是否渲染的判断,如果在JSX中使用bind或箭头函数绑定this会造成子组件每次获取的函数都是一个新的引用,这破坏了shouldComponentUpdate的逻辑,引入了无意义的重复渲染,因此需要在render调用之前就将事件处理方法与this绑定,在每次render`调用中获取同样的引用。

当前比较流行的事前绑定this的方法有2种,其一使用类属性的语法:

class Foo {
    onClick = e => {
        // ...
    }
};

其二使用@autobind的装饰器:

class Foo {
    @autobind
    onClick(e) {
        // ...
    }
}

使用类属性语法虽然可以避免引入一个autobind的实现,但存在一定的缺陷:

因此,推荐使用@autobind装饰器实现this的事先绑定,推荐使用库core-decorators提供的相关装饰器实现。

amenzai commented 5 years ago

[建议]为函数组件添加PureComponent能力

函数组件并非一定是纯组件,因此其shouldComponentUpdate的实现为return true;,这可能导致额外的无意义渲染,因此推荐使用高阶组件为其添加shouldComponentUpdate的相关逻辑。

推荐使用react-pure-stateless-component库实现这一功能。

amenzai commented 5 years ago

[强制]所有组件均需声明propTypes。

propsTypes在提升组件健壮性的同时,也是一种类似组件的文档的存在,有助于代码的阅读和理解。

[强制]对于所有非isRequired的属性,在defaultProps中声明对应的值。

声明初始值有助于对组件初始状态的理解,也可以减少propTypes对类型进行校验产生的开销。

对于初始没有值的属性,应当声明初始值为null而非undefined。

amenzai commented 5 years ago

[强制]使用onXxx形式作为props中用于回调的属性名称。

使用统一的命名规则用以区分props中回调和非回调部分的属性,在JSX上可以清晰地看到一个组件向上和向下的逻辑交互。

对于不用于回调的函数类型的属性,使用动词作为属性名称。

[强制]高阶组件使用camelCase命名。

高阶组件事实上并非一个组件,而是一个“生成组件类型”的函数,因此遵守JavaScript函数命名的规范,使用camelCase命名。

[建议]使用withXxx或xxxable形式的词作为高阶组件的名称。

高阶组件是为组件添加行为和功能的函数,因此使用如上形式的词有助于对其功能进行理解。

[建议]作为组件方法的事件处理函数以具备业务含义的词作为名称,不使用onXxx形式命名。