es6的class寫法與es5的createClass都有哪些區別?


1. 前言

在使用React的時候,根據官方文檔,發現了兩種創建組件的方式。一種是使用React.createClass({})的方式來創建,還有一種是使用ES6的class並繼承React.Component來創建。 剛開始學的時候自己覺得有點迷,並且一直都是使用ES6語法來創建組件(畢竟先進嘛)。這段時間稍稍有空,來鑽研一下兩者之間的區別。

2. 先看官方怎么說

Reactv0.13版本開始,就可以使用ES6的語法來代替React.createClass({})這種寫法了。但是官方也有所聲明,在未找到當前mixin用例的代替方案時,都不會放棄React.createClass({})這樣的寫法。 官方文檔地址 搬運部分文檔

Today, we’re happy to release React v0.13! The most notable new feature is support for ES6 classes, which allows developers to have more flexibility when writing components. Our eventual goal is for ES6 classes to replace React.createClass completely, but until we have a replacement for current mixin use cases and support for class property initializers in the language, we don’t plan to deprecate React.createClass.

3. 對比

React.createClass({})的工作,基本上都可以使用ES6語法來代替。例如,設置state

var Msg = React.createClass({
    getInitialState: function() {
        return {
            msg: "HW" 
        };
    }
})
class Msg extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            msg: "HW"
        }
    }
}

 

由以上例子可以看出,兩種書寫方式還是有較大的區別的。

3.1. 區別1. 構造函數

React.createClass({})中,是不用寫構造函數並且傳入props再調用super(props)的,而在ES6中類的構造函數需要接受props作為參數並調用方法。

3.2. 區別2. 初始化狀態

React.createClass({})中需要書寫方法getInitialState來對狀態進行初始化,而在ES6語法中,這些都可以放在構造函數內完成。

3.3. 區別3. 函數綁定

我們雖然可以使用ES6語法來定義一些事件方法,但是可惜的是,這些我們定義在class中的方法並沒有自動綁定到我們希望的對象上,換句話說,就是函數作用域內的this的指向不對。 可以看這樣一個簡單的組件。

import React from 'react'
export default class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            msg: "HW"
        }
    }

    handleClick() {
        this.setState({
            msg: "Click!"
        })
    }

    render() {
        return (
            <div>
                <p>{this.state.msg}</p>
                <button onClick={this.handleClick}>Click!</button>
            </div>
        )
    }
}

 

渲染結果是這樣 img這時如果點擊按鈕,會報錯 img這就是因為上文所述,this的作用域不對導致的。 解決方法很簡單,在構造方法內加上這么一句話就可以。

this.handleClick = this.handleClick.bind(this)

如果方法很多,這個方式就很不舒服,可以使用react-autobind

3.4. 區別4. 其他配置

React.createClass({})中,propTypesdefaultProps的定義無需太過費心。 而在ES6語法中,情況又有所不同。

import React from 'react'

class App extends React.Component {
    constructor(props) {
        super(props)
    }
    render() {
        return (
            <div>
                <p>{this.props.bar}</p>
            </div>
        )
    }
}

App.propTypes = {
    bar: React.PropTypes.string
}

App.defaultProps = {
    bar: "barbar"
}
export default App

 

而如果使用了babel-preset-stage-2,我們可以寫出更有感覺的代碼。

import React from 'react'

export default class App extends React.Component {
    static propTypes = {
        bar: React.PropTypes.string
    }
    static defaultProps = {
        bar: "barbar"
    }
    constructor(props) {
        super(props)
    }
    render() {
        return (
            <div>
                <p>{this.props.bar}</p>
            </div>
        )
    }
}

 

4. 總結

以上是我在實際項目中、網絡中、官方文檔中搜集到的一些關於React.createClass({})ES6語法創建組件的不同點。如果有遺漏的話,希望我們可以多多探討。

在具體項目中,我們應該用哪個?

這個問題其實探討的意義不是很大。 ES6寫法雖然人氣日益上漲,但並不是唯一的寫法。而且官方也說了,暫時不會放棄對React.createClass({})的維護。 如果是個人開發者,完全可以依據個人喜好來選擇使用。 如果是項目組,當然需要優先考慮項目組的代碼規范。 不過我認為,了解這兩者之間的不同點,並且掌握這兩種方式是非常有必要的。

2017年07月18日更新

其實還有一個非常重要的創建組件的方式——函數式組件。 它的創建方式類似於這樣:

function Button(props) {
  return <button onClick={props.onClick}>{props.title}</button>
}

 

這是在React 0.14版本之后提供的方法。 這種創建組件的方式相對ES5ES6來說簡單了不少。尤其是其內部沒有包含任何狀態(state),我們可以稱,他是一個“純”的組件。

關於純:目前已知的“純”類最具有代表性的是純函數,其定義為“傳入相同的輸入,永遠都會有相同的輸出”的無副作用的函數。那么類比到組件身上可以定義純組件為“傳入相同的props,永遠都會得到相同的組件”。即組件不會受內部狀態(state)影響

這樣寫的好處有很多,我可以簡單舉幾例: \1. 可以遵循Reactcontroller view模式。我們可以定義controller來保存組件狀態,並單獨定義純組件來作為view渲染。參考:controller view模式flux架構入門教程 \2. 語法簡潔! 其具體可以體現在: function Button(props) { return <button onClick={props.onClick}>{props.title}</button> } 精簡: let Button = (props) => { return <button onClick={props.onClick}>{props.title}</button> 再精簡: let Button = (props) => ( <button onClick={props.onClick}>{props.title}</button>) \3. 占用內存少 和其他類型的創建相比,這是顯而易見的。 \4. 可擴展占性強 React是數據驅動型框架,數據決定了組件的渲染結果。而如果將數據操作綁定在組件內部成為狀態(state)的話會增加組件與數據之間的耦合性。編寫純組件並且使用controller view模式可以有效降低數據與組件之間的耦合度,使組件的復用能力、擴展能力大大提高。並且使用函數的方式創建組件,可以更好的結合函數式編程,使代碼更加優雅。

當然了,其也有比較嚴重的缺點: 沒有生命周期函數

因此,對於如何選擇定義組件的方式,我還是保留之前的想法,“優先考慮項目組的代碼規范”,並且還需要結合實際來考慮,才是最佳之舉。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM