平时我们写React
组件的时候一般就是直接用类组件
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
现在你可以不使用ES6
的类语法,而用React.createClass
函数进行处理
var Greeting = React.createClass({
render: function() {
return <h1>Hello, {this.props.name}</h1>;
}
});
虽然上面的代码中render
这个函数基本和ES6
语法的类组件没有多少区别,但是它们的区别个人认为还是比较大的。
1.PropTypes
属性检测和defaultProps
值区别
ES6
语法
class Greeting extends React.Component {
// ...
}
Greeting.propTypes = {
name: React.PropTypes.string
};
Greeting.defaultProps = {
name: 'Mary'
};
非ES6
语法
var Greeting = React.createClass({
propTypes: {
name: React.PropTypes.string
},
getDefaultProps: function() {
return {
name: 'Mary'
};
},
// ...
});
对于propTypes
大家还好理解,跟类组件基本一样,但是defaultProps
却需要使用一个函数进行返回,这一点大家需要注意。
2.初始化this.state
状态
ES6
的语法非常简单,就是在construtor
构造函数中直接对this.state
赋值即可
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
// ...
}
而在非ES6
中,我们要用函数getInitialState
函数进行初始化
var Counter = React.createClass({
getInitialState: function() {
return {count: this.props.initialCount};
},
// ...
});
3.自动绑定机制
在React
组件描述为类组件时,它的定义和ES6
语法中类的定义语法是一模一样的,但是这有个非常尴尬的事情,就是内部的函数都不会绑定自我的实例,我们在前面也一直在constructor
构造函数中用.bind(this)
来绑定自身实例
class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello!'};
// 必须加,代码实现绑定
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert(this.state.message);
}
render() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
而用React.createClass
创建的类则非常有意思,它帮你自动绑定了,不需要你用bind
进行绑定。
var SayHello = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleClick: function() {
alert(this.state.message);
},
render: function() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
});
如果你觉得上面的代码不够新鲜,那么新鲜得来了
class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello!'};
}
//这个语法够新鲜吧,简直是逆天了,用箭头函数和赋值来定义类内的函数
//然而这个语法更像是个表达式赋值,而不是一个函数声明
//所以如果不是为了装逼,请不要用这个语法
handleClick = () => {
alert(this.state.message);
}
render() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
上面的代码注释中说了些话,主要是为了让大家警惕,上面的那个语法属于实验性质的,它最终有可能不会加入到ES
语法中,所以最好不要用。
几点建议
如果你是用
ES6
语法的类组件,请在construcotr
构造函数中使用bind
函数进行绑定如果你要用箭头函数的话,请在事件绑定中做
onClick={(e) => this.handleClick(e)}
能用
React.createClass()
就用它
4.Mixins
多继承模式
ES6
没有推出多继承的语法,而React官方说很多代码库中都有使用Mixins
将多个对象合并为一个对象,然而如果没有必要,它并不推荐你这么做
但是有时候允许你在React.createClass
中使用mixins
处理(createClass
在方法上实现了mixins
多继承机制),比如说,我们可以将摧毁函数共用,用于最终组件摧毁时都会摧毁的资源,
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.forEach(clearInterval);
}
};
var TickTock = React.createClass({
mixins: [SetIntervalMixin],
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000);
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});
ReactDOM.render(
<TickTock />,
document.getElementById('example')
);
如下的代码即,createClass
创建对象时,会将SetIntervalMixin
对象的方法和属性继承过来
mixins: [SetIntervalMixin]
使用mixins
一定要确保最终将所有组件都摧毁了。
下一篇将讲
React
中不用JSX
的痛