1. 程式人生 > >React.js中ES6 和 ES5寫法的一些差別

React.js中ES6 和 ES5寫法的一些差別

1、 Modules引入和輸出方式
ES5 使用 CommonJS 標準,一般使用 require() 用法引入模組:

var React = require('react');
var MyComponent = require('./MyComponent');

ES5輸出模組:

module.exports = MyComponent;

ES6 + import語法引入模組:

import React from 'react';
import MyComponent from './MyComponent';

ES6 輸入模組:

export default class
MyComponent extends React.Component{
}

2、 Classes, 建立元件Component的方法
ES5 的React.createClass()用法

var Photo = React.createClass({
        render: function(){
            return (
                <div>
                    <images alt={this.props.description} src={this.props.src} />
                </div>
            )
        }
    });
ReactDOM.render(<Photo />, document.getElementById('root'
));

es6 + class用法

class Photo extends React.Component{
        render(){
            return (
                <div>
                    <images alt={this.props.description} src={this.props.src} />
                </div>
            )
        }
    };
ReactDOM.render(<Photo />, document.getElementById('root'
));

在 ES5 我們會在 componentWillMount 生命週期定義希望在 render 前執行,且只執行一次的任務

var Photo = React.createClass({
        componentWillMount: function(){}
    })

在 ES6+ 則是定義在 constructor 中

class Photo extends React.Component{
        constructor(props){
            super(props);
            // 原本在 componentWillMount 操作的動作可以放在這
        }
    }

3、 Method 方法定義
ES5定義方法語法:

var Photo = React.createClass({
        handleClick: function(e){},
        render: function(){}
    });

ES6可省略掉function和逗號( ’ , ’ ):

class Photo extends React.Component{
        handleClick(e){}
        render(){}
    }

4、Property 屬性初始化
ES5 語法 使用propTypes 和 getDefaultProps來定義屬性(props)的預設值和型別:

var Todo = React.createClass({
        getDefaultProps: function(){
            return {
                checked: false,
                maxLength: 10,
            };
        },
        propTypes: {
            checked: React.PropTypes.bool.isRequired,
            maxLengh: React.PropTypes.number.isRequired
        }, 
        render: function(){
            return ();
        }
    })

ES6語法,使用 class 中的靜態屬性(static properties)來定義:

class Todo extends React.Component{
        static defaultProps = {
            checked: false,
            maxLength: 10,
        };
        static propTypes = {
            checked: React.PropTypes.bool.isRequired,
            maxLengh: 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,
        maxLengh: React.PropTypes.number.isRequired
    };

5、 State 狀態
ES5 語法 使用 getInitialState 去初始化 state:

var Todo = React.createClass({
        getInitialState: function(){
            return {
                maxLength: this.props.maxLength
            }
        }
    })

在 ES6+ 中初始化 state 有兩種寫法,一種如下:

class Todo extends React.Component{
        state = {
            maxLength: this.props.maxLength,
        }
    }

另一種寫在constructor中(建議用這種,方便做一些運算):

class Todo extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                maxLength: this.props.maxLength,
            }
        }
    }

6、 Arrow functions 箭頭函式
ES5語法,在 React.createClass() 下,預設幫你繫結好 method 的 this,你無須自行繫結:

var TodoBtn = React.createClass({
        handleButtonClick: function(e) {
            // 此 this 指到 component 的例項(instance),而非 button
            this.setState({showOptionsModal: true});
        },
        render: function(){
            return (
                <div>
                    <Button onClick={this.handleButtonClick}>{this.props.label}</Button>
                </div>
            )
        },
    });

ES6+ 推薦使用 bind 繫結 this 或使用 Arrow functions(它會綁定當前 scope 的 this context)兩種方式:

class TodoBtn extends React.Component{
        handleButtonClick(e){
            // 確認繫結 this 指到 component instance
            this.setState({toggle: true});
        }
        render(){
            // 這邊可以用 this.handleButtonClick.bind(this) 手動繫結或是 Arrow functions () => {} 用法
            return (
                <div>
                    <Button onClick={this.handleButtonClick.bind(this)} onClick={(e)=> {this.handleButtonClick(e)} }>{this.props.label}</Button>
                </div>
            )
        },
    };

無論是 bind 或是 Arrow functions,每次執行回傳都是指到一個新的函式,若需要再呼叫到這個函式,要先把它存起來:

class TodoBtn extends React.Component{
        constructor(props){
            super(props);
            this.handleButtonClick = this.handleButtonClick.bind(this);
        }
        componentWillMount(){
            Btn.addEventListener('click', this.handleButtonClick);
        }
        componentDidmount(){
            Btn.removeEventListener('click', this.handleButtonClick);
        }
    };

7、動態屬性名和模板字串
ES5 我們要動態設定屬性名,往往需要多寫幾行程式碼才能達到目標:

var Todo = React.createClass({
        onChange: function(inputName, e){
            var stateToSet = {};
            stateToSet[inputName + 'Value'] = e.tartet.value;
            this.setState(stateToSet);
        }
    })

ES6+寫法相對簡單:

class Todo extends React.Component{
        onChange(inputName, e) {
            this.setState({
                [`${inputName}Value`]: e.target.value,
            })
        }
    }