1. 程式人生 > >React: ES5 和 ES6 比較

React: ES5 和 ES6 比較

React 同時支援 ES5 和 ES6 兩種語法。通過 Babel 可以編譯 ES 6 和 JSX , 把他們轉譯成 ES 5 。

今早發現 ES 7都已經正式納入標準了, ES 真是當之無愧程式語言中的“標準帝”。伴隨著學習和使用經驗, ,也用到了一些 ES 7 的語法,這裡主要對React 中 ES5 和 ES6 兩種語法做一個對比和歸納。

  1. createClass vs class

    首先上程式碼,直觀感受一下同一個 component 元件使用 ES5 和 ES6 兩種不同的語法寫出的程式碼。

    var InputControlES5 = React.createClass({
        propTypes: {
        initialValue: React.PropTypes.string
            },
        defaultProps: {
        initialValue: ''
}, // Set up initial state getInitialState: function() { return { text: this.props.initialValue || 'placeholder' }; }, handleChange: function(event) { this.setState({ text: event.target.value }); }, render: function()
{
return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } });
    class InputControlES6 extends React.Component {
        constructor(props) {
            super
(props); // Set up initial state this.state = { text: props.initialValue || 'placeholder' }; // Functions must be bound manually with ES6 classes this.handleChange = this.handleChange.bind(this); } handleChange(event) { this.setState({ text: event.target.value }); } render() { return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } } InputControlES6.propTypes = { initialValue: React.PropTypes.string }; InputControlES6.defaultProps = { initialValue: '' };
  1. 主要區別:

    1. 函式繫結:
      ES 5 中的 createClass 沒有函式 this 繫結問題的困擾。每個 property 屬性上的函式都自動繫結,通過 this.functionName 就能refer 到函式, 在呼叫函式時 this 能夠正確正確地指向。

      在 ES 6 寫法中, 函式卻沒有自動繫結, 只能通過手動繫結完成。 解決辦法有以下幾種:

      • 最佳的辦法是在 constructor 中完成, 栗子如上程式碼。

      • 還用現成的一些 npm 包可以幫我們輕鬆搞定, 比如 react-autobind 和 autobind-decorator

      • 除此之外,還可以在 render 方法中內聯繫結:

            // Use `.bind`:
            render() {
                return (
                         <input onChange={this.handleChange.bind(this)}
                             value={this.state.text} />
                );
            }

            // --- OR ---

            // Use an arrow function:
            render() {
                return (
                     <input onChange={() =>                     this.handleChange()}
                    value={this.state.text} />
                );
            }

箭頭函式可以解決 this 繫結問題。但這兩種方法效率不如第一種, 每次 render 呼叫的時候,都會建立一個新函式。

  • 最後一種方法就是直接使用箭頭函式重寫原來的函式。
            // the normal way
            // requires binding elsewhere
            handleChange(event) {
              this.setState({
                text: event.target.value
              });
            }

            // the ES7 way
            // all done, no binding required
            handleChange = (event) => {
              this.setState({
                text: event.target.value
              });
            }

直接用箭頭函式寫原來的函式方法, 自動完成了 this 繫結的任務, 函式內的 this 指向 component 元件。但這種寫法尚處於試驗階段, 目前還不是官方 ES 6 中的內容。不過,利用 Babel , 可以放心使用這個方法。

  1. Constructor 建構函式應該呼叫 super

    ES6 中的 constructor 需要以 props 作為引數, 並呼叫 super(props) 。 ES 5 的寫法中沒有這一步。

    1. class 和 createClass

    建立類的方式不同: ES 5 中使用 React.createClass , ES 6 中通過 class extends React.Component 實現。import React, {Component} from ‘react’

    ES 6 的寫法在同一個檔案中有多個 components 時非常方便其他檔案 import引用。

    1. 初始 state 狀態的設定

    ES 5 中 React.createClass 裡面有一個 initialState 函式, 在每次 component 元件掛載 mount 時候都會被呼叫。

    ES 6 的 class 中使用 constructor , 然後呼叫 super , 接著直接設定 state。

    1. propTypes 屬性型別和 defaultProPs 預設屬性

    ES 5 中 React.createClass 在傳入的物件上定義了propTypes 屬性型別和 defaultProPs 預設屬性。

    ES 6 的 class 中, propTypes 屬性型別和 defaultProPs 預設屬性成為了 class 本身的 properties 屬性, 所以需要在 class 定義之後才能定義。

    利用 ES 7, 可以更方便的完成屬性型別和屬性預設值的設定。

    class Person extends React.Component {
        static propTypes = {
        name: React.PropTypes.string,
        age: React.PropTypes.string
      };
    
      static defaultProps = {
        name: '',
        age: -1
      };
    
      ...
    }
    

參考: