[react] reactjs 在ES6中的实现
Functional Component 写法
单纯地 render UI 的 stateless components,
没有内部状态、没有实作物件和 ref,没有生命周期函数。
若非需要控制生命周期的话可多使用 stateless components 获得比较好的性能
```
const MyComponent = (props) => (
<div>Hello, {props.name}</div>
);
ReactDOM.render(<MyComponent name="Mark"/>, document.getElmentById('app'));
```
#Property initializers
```
//原始写法
var Todo = React.createClass({
getDefaultProps: function() {
return {
checked: false,
maxLength: 10,
};
},
propTypes: {
checked: React.PropTypes.bool.isRequired,
maxLength: React.PropTypes.number.isRequired
},
render: fucntion() {
return();
}
});
//es6写法
class Todo extends React.Component {
static defaultProps = {
checked: false,
maxLength: 10,
};
static propTypes = {
checked: React.PropTypes.bool.isRequired,
maxLength: React.PropTypes.number.isRequired
};
render() {
return();
}
}
//另一种es6写法
class Todo extends React.Component {
render() {
return (
<View />
);
}
}
Todo.defaultProps = {
checked: false,
maxLength: 10,
};
Todo.propTypes = {
checked: React.PropTypes.bool.isRequired,
maxLength: React.PropTypes.number.isRequired,
};
```
#State
```
//原始写法
var Todo = React.createClass({
getInitialState: function() {
return {
maxLength: this.props.maxLength,
};
},
});
//es6
class Todo extends React.Component {
state = {
maxLength: this.props.maxLength,
}
}
//es6
class Todo extends React.Component {
constructor(props){
super(props);
this.state = {
maxLength: this.props.maxLength,
};
}
}
```
#Destructuring & spread attributes
```
class Todo extends React.Component {
render() {
var {
className,
...others, // ...others 包含 this.props 除了 className 外所有值。this.props = {value: 'true', title: 'header', className: 'content'}
} = this.props;
return (
<div className={className}>
<TodoList {...others} />
<button onClick={this.handleLoadMoreClick}>Load more</button>
</div>
);
}
}
//若this.props中含有className,则被className="main"覆盖
<div {...this.props} className="main">
…
</div>
```
#class
//old var Header = React.createClass({ render: function () { return (<header id="header"> <h1>TODOs</h1> <app.TodoTextInput id="new-todo" placeholder="想干啥?" onSave={this.props.onSave} /> </header>); } }); //new class Header extends React.Component { render() { return (<header id="header"> <h1>TODOs</h1> <TodoTextInput id="new-todo" placeholder="想干啥?" onSave={this.props.onSave} /> </header>); } }
#使用const let 代替 var
//old var ENTER_KEY_CODE = 13; //new const ENTER_KEY_CODE = 13; //old render: function () { var todo = this.props.todo; var input; if (this.state.isEditing) { input = <app.TodoTextInput className="edit" onSave={this._onUpdateText} value={todo.text} />; } var className = { 'completed': todo.complete, 'editing': this.state.isEditing }; var classes = []; var hasOwn = {}.hasOwnProperty; for (var key in className) { if (hasOwn.call(className, key) && className[key]) { classes.push(key); } } ... //new render() { let todo = this.props.todo; let input; if (this.state.isEditing) { input = <TodoTextInput className="edit" onSave={this._onUpdateText.bind(this)} value={todo.text} />; } let className = { 'completed': todo.complete, 'editing': this.state.isEditing }; let classes = []; let hasOwn = {}.hasOwnProperty; for (let key in className) { if (hasOwn.call(className, key) && className[key]) { classes.push(key); } } ...
#Properties类型检查
//old propTypes: { allTodos: React.PropTypes.array.isRequired }, ... //new Footer.propTypes = { allTodos: React.PropTypes.array.isRequired };
#Properties默认值
//old getDefaultProps : function () { return { value: '' }; }, ... //new TodoTextInput.defaultProps = { value: '' };
#静态变量
//new 类型检查 //inner Footer static propTypes = { allTodos: React.PropTypes.array.isRequired }; //new 默认值 //inner TodoTextInput static defaultProps = { value: '' };
#State初始化方式
//old //inner TodoApp var TodoApp = React.createClass({ getInitialState: function () { return state }, ... //new class TodoApp extends React.Component { constructor(props) { super(props); this.state = initstate; } ...
#手动绑定
使用ES6语法后,React将原来的默认绑定至所在Component的功能去掉了,所以需要自己处理
//old render: function () { state.areAllComplete = this._areAllComplete(); return ( <div> <Header onSave={this._onSave}/> <MainSection allTodos={this.state.allTodos} areAllComplete={this.state.areAllComplete} updateText={this._updateText} toggleCompleteAll={this._toggleCompleteAll} toggleComplete={this._toggleComplete} destroy={this._destroy} selectedFilter={this.state.selectedFilter} /> <Footer allTodos={this.state.allTodos} destroyCompleted={this._destroyCompleted} selectedFilter={this.state.selectedFilter} onFilter={this._filter} /> </div> ); }, //new // inner TodoApp render() { this.state.areAllComplete = this._areAllComplete(); return ( <div> <Header onSave={this._onSave.bind(this)}/> <MainSection allTodos={this.state.allTodos} areAllComplete={this.state.areAllComplete} updateText={this._updateText.bind(this)} toggleCompleteAll={this._toggleCompleteAll.bind(this)} toggleComplete={this._toggleComplete.bind(this)} destroy={this._destroy.bind(this)} selectedFilter={this.state.selectedFilter} /> <Footer allTodos={this.state.allTodos} destroyCompleted={this._destroyCompleted.bind(this)} selectedFilter={this.state.selectedFilter} onFilter={this._filter.bind(this)} /> </div> ); }
#使用=>代替手动绑定
箭头函数就是个简写形式的函数表达式,并且它拥有词法作用域的this值(即不会新产生自己作用域下的this, arguments, super 和 new.target 等对象)。
// => //innert TodoApp // _destroy(id) { change to _destroy = (id) => { _destroy = (id) => { this.state.allTodos = this.state.allTodos.filter(function (todo) { return todo.id !== id; } ); this.setState(this.state); }; //然后就不需要手工绑定了 render() { this.state.areAllComplete = this._areAllComplete(); return ( <div> <Header onSave={this._onSave.bind(this)}/> <MainSection allTodos={this.state.allTodos} areAllComplete={this.state.areAllComplete} updateText={this._updateText.bind(this)} toggleCompleteAll={this._toggleCompleteAll.bind(this)} toggleComplete={this._toggleComplete.bind(this)} destroy={this._destroy} selectedFilter={this.state.selectedFilter} /> <Footer allTodos={this.state.allTodos} destroyCompleted={this._destroyCompleted.bind(this)} selectedFilter={this.state.selectedFilter} onFilter={this._filter.bind(this)} /> </div> ); }