React.createClass 与 extends Component 的区别
这是 React 发展过程中的一个重要变化,主要体现在 React 15.5 版本之前和之后的写法差异。
1. 语法定义区别
React.createClass (旧版)
// React 15.5 之前的写法
const MyComponent = React.createClass({
// 必须定义 getInitialState
getInitialState: function() {
return {
count: 0
};
},
// 自动绑定 this
handleClick: function() {
this.setState({ count: this.state.count + 1 });
},
render: function() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
});
extends Component (新版)
// React 15.5 及之后的写法
class MyComponent extends React.Component {
constructor(props) {
super(props);
// 在构造函数中初始化 state
this.state = {
count: 0
};
// 需要手动绑定 this
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}
2. 主要区别详解
2.1 状态初始化
React.createClass:
const Component = React.createClass({
getInitialState: function() {
return { name: 'John' };
}
});
extends Component:
class Component extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'John' };
}
}
2.2 this 绑定
React.createClass – 自动绑定:
const Component = React.createClass({
handleClick: function() {
// this 自动绑定到组件实例
console.log(this); // 组件实例
},
render: function() {
return <button onClick={this.handleClick}>Click</button>;
}
});
extends Component – 需要手动绑定:
class Component extends React.Component {
constructor(props) {
super(props);
// 方式1:在构造函数中绑定
this.handleClick = this.handleClick.bind(this);
}
// 方式2:使用类属性+箭头函数 (实验性语法,需要 Babel)
handleClick = () => {
console.log(this); // 组件实例
}
// 方式3:在 render 中绑定
render() {
return (
<div>
<button onClick={this.handleClick.bind(this)}>Click</button>
{/* 或使用箭头函数 */}
<button onClick={() => this.handleClick()}>Click</button>
</div>
);
}
}
2.3 Props 类型验证
React.createClass:
const Component = React.createClass({
propTypes: {
name: React.PropTypes.string,
age: React.PropTypes.number
},
getDefaultProps: function() {
return {
name: 'Anonymous',
age: 18
};
}
});
extends Component:
class Component extends React.Component {
static propTypes = {
name: PropTypes.string,
age: PropTypes.number
};
static defaultProps = {
name: 'Anonymous',
age: 18
};
}
// 或者写在类外部
Component.propTypes = {
name: PropTypes.string,
age: PropTypes.number
};
Component.defaultProps = {
name: 'Anonymous',
age: 18
};
2.4 Mixins 支持
React.createClass – 支持 mixins:
const LogMixin = {
componentDidMount: function() {
console.log('Component mounted');
}
};
const Component = React.createClass({
mixins: [LogMixin],
// ...
});
extends Component – 不支持 mixins:
// 不支持 mixins,需要使用高阶组件或 Render Props
const withLogging = (WrappedComponent) => {
return class extends React.Component {
componentDidMount() {
console.log('Component mounted');
}
render() {
return <WrappedComponent {...this.props} />;
}
};
};
class Component extends React.Component {
// ...
}
export default withLogging(Component);
3. 生命周期方法差异
React.createClass
const Component = React.createClass({
// 已废弃的生命周期
componentWillMount: function() {},
componentWillReceiveProps: function() {},
componentWillUpdate: function() {},
render: function() {
return <div>Hello</div>;
}
});
extends Component
class Component extends React.Component {
// 新的生命周期(React 16.3+)
static getDerivedStateFromProps(props, state) {
// 返回更新的 state 或 null
return null;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// 在 DOM 更新前调用
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// 使用 getSnapshotBeforeUpdate 的返回值
}
render() {
return <div>Hello</div>;
}
}
4. 性能差异
React.createClass:
- 包含更多的包装和检查
- 性能稍差
- 体积更大
extends Component:
- 更接近原生 JavaScript 类
- 性能更好
- 体积更小
5. 现代 React 中的写法
使用 Hooks (React 16.8+)
import React, { useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
使用类组件 (当前标准)
class MyComponent extends React.Component {
state = {
count: 0
};
handleClick = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}
6. 迁移建议
从 React.createClass 迁移到 extends Component
// 旧代码
const OldComponent = React.createClass({
getInitialState: function() {
return { name: 'John' };
},
handleClick: function() {
this.setState({ name: 'Jane' });
},
render: function() {
return <button onClick={this.handleClick}>{this.state.name}</button>;
}
});
// 新代码
class NewComponent extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'John' };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ name: 'Jane' });
}
render() {
return <button onClick={this.handleClick}>{this.state.name}</button>;
}
}
7. 总结对比表
| 特性 | React.createClass | extends Component |
|---|---|---|
| 语法 | 工厂函数 | ES6 类 |
| 状态初始化 | getInitialState() | constructor() 中的 this.state |
| this 绑定 | 自动绑定 | 需要手动绑定 |
| PropTypes | 在对象内部定义 | 静态属性或类外部定义 |
| defaultProps | getDefaultProps() | 静态属性 |
| Mixins 支持 | 支持 | 不支持 |
| 性能 | 稍差 | 更好 |
| 推荐使用 | 已废弃 | 推荐(或使用函数组件+Hooks) |
8. 最佳实践
- 新项目:使用函数组件 + Hooks
- 现有类组件:使用
extends Component语法 - 避免使用:
React.createClass(已废弃) - 绑定处理:使用类属性箭头函数或构造函数绑定
- 状态管理:考虑使用 Hooks 替代类组件状态
React 团队已经明确表示 React.createClass 已被废弃,建议所有新项目使用函数组件和 Hooks,或者至少使用 ES6 类组件语法。
THE END


