正文
将 React 组件从 React 0.12 通过 createClass
定义的组件重构为基于 0.13 版本使用 ES6 类定义的组件只需要以下简单的几步。在后文中将一步一步的给予说明。
第一步 - 从组件构造函数中取出 propTypes
和 getDefaultProps
放到组件属性上
另外的一个变化之处是在 React 0.13 版本中, props
属性被定义为 immutable data(不可变数据),所以 getDefaultProps
作为一个函数将不能在继续使用,因此也需要将其重构到构造函数之外。
Before:
var ExampleComponent = React.createClass({
propTypes: {
aStringProps: React.PropTypes.string
},
getDefaultProps: function() {
return { aStringProps: '' }
}
})
After:
var ExampleComponent = React.createClass({...});
ExampleComponent.propTypes = {
aStringProps: React.PropTypes.string
};
ExampleComponent.defaultProps = {
aStringProps: ''
}
第二步 - 从 createClass
到使用 ES6 Class 语法定义组件
ES6 Class 语法比起传统的对象字面量更为简洁。对于方法的定义不需要再使用 function
关键字,也不需要 ,
来分开多个方法。
Before:
var ExampleComponent = React.createClass({
render: function() {
return <div onClick={ this._handleClick }>Hello World!</div>
},
_handleClick: function() {
console.log(this);
}
})
After:
class ExampleComponent extends {
render() {
return <div onClick={ this._handleClick }>Hello World!</div>
}
_handleClick() {
console.log(this)
}
}
第三步 - 绑定实例方法和回调到实例上
Before:
class ExampleComponent extends {
render() {
return <div onClick={ this._handleClick }> Hello World! </div>
}
_handleClick() {
console.log(this); // this is undefined
}
}
After:
class ExampleComponent extends {
constructor() {
super();
this._handleClick = this._handleClick.bind(this);
}
render() {
return <div onClick={ this._handleClick }> Hello World! </div>
}
_handleClick() {
console.log(this); // this is an ExampleComponent
}
}
在文章结尾将会介绍我们对 Component 类的扩展,该类将会更好的实现自动绑定的过程。
第四步 - 将初始 state 定义移动到构造函数中
React 团队推荐使用一种更符合语义的方法来定义初始 state(在构造函数中将初始值存放在对应属性上)。也就是可以在构造函数中将 getInitialState
方法中的返回值赋值到 该实例对象的 this.state
属性上。
Before:
class ExampleComponent extends {
getInitialState() {
return Store.getState();
}
constructor() {
super();
this._handleClick = this._handleClick.bind(this);
}
// ...
}
After:
class ExampleComponent extends {
constructor() {
super();
this._handleClick = this._handleClick.bind(this);
this.state = Store.getState();
}
// ...
}
Conclusion
使用上面提到的少许的几步将一个存在的 React 组件转化为 ES6 Class 语法定义的组件是很简单的。同时直到 JavaScript 语法上有 mixins
特性之前使用 React.createClass
也是不被反对的。
Bonus Step - 更简洁的 this 绑定方法:
Before:
class ExampleComponent extends {
constructor() {
super();
this._handleClick = this._handleClick.bind(this);
this._handleFoo = this._handleFoo.bind(this);
}
// ...
}
After:
class BaseComponent extends {
_bind(...methods) {
methods.forEach( (method) => this[method] = this[method].bind(this) );
}
}
class ExampleComponent extends BaseComponent {
constructor() {
super();
this._bind('_handleClick', '_handleFoo');
}
// ...
}