React與ES6(四)ES6如何處理React mixins


React與ES6系列:

  1. React與ES6(一)開篇介紹
  2. React和ES6(二)ES6的類和ES7的property initializer
  3. React與ES6(三)ES6類和方法綁定
  4. React與ES6(四)ES6如何處理React mixins

在使用React.createClass()的時候你也許使用過一個所謂的mixin的東西。使用它,你可以給React組件天劍很多其他的功能。這個概念不止用在React上,也用在很多其他的編程語言或者框架上。

在ES6中不能夠在使用React的mixin機制。本文不會糾結於原因為何。我們只關注ES6中的替代方法。

##High-Order Component 或者可以叫做高階組件。

我們使用前文中使用的CartItem組件作為例子,在其中顯示一個每秒計數增加1的timer。

為了更好的演示,我們不修改CartItem的代碼。相反的我們要提供一些組件,這些組件會封裝CartItem並且給CartItem增強一些另外的方法。這樣的一個組件就叫做High-Order Comoentn

上面的介紹可能還是有些模糊,不要緊隨着本文步步深入一切都會變得清晰。

我們假設這個Hight-Order Component叫做IntervalEnhance,存放在一個叫做intervalEnhance.jsx的文件中。那么我們的CartItem應該怎么改呢?

import React from 'react';
// 1
import {IntervalEnhance} from './IntervalEnhance';

class CartItem extends React.Component {
    //...略...
}
//2
export default IntervalEnhance(CartItem);

解釋:

  1. 引入高階組件IntervalEnhance
  2. export高階組件包裝增強后的CartItem

下滿就看看告誡組件是怎么定義的:

//@flow

import React from 'react';
//1
export var IntervalEnhance = ComposeComponent => class extends ComposeComponent {
    // 2
    static displayName = 'ComponentEnhancedWithIntervalHOC';

    constructor(props) {
        super(props);
        this.state = {
            seconds: 0
        };
    }
    // 3
    componentDidMount() {
        this.interval = setInterval(this.tick.bind(this), 1000);
    }
    // 3
    componentWillUnmount() {
        clearInterval(this.interval);
    }

    tick() {
        this.setState({
            seconds: this.state.seconds + 1000
        });
    }

    render() {
        return (
            // 4
            <ComposeComponent {...this.props} {...this.state} />
        );
    }
}

解釋:

  1. ComposeComponent => class extends React.Comonent這句。還記得箭頭函數嗎?沒錯,這就是一個箭頭函數。這個函數接受一個組件為輸入參數,返回一個類。ComposedComponent就是輸入參數,也就是需要包裝增強的組件。export var IntervalEnhance就是把前面定義的函數命名為IntervalEnhance export出去給其他的模塊使用。
  2. displayName設定為ComponentEnhancedWithIntervalHOC是為了在DevTools中方便調試。在DevTools里這個組件就會被叫做ComponentEnhancedWithIntervalHOC
  3. 組件生命周期不同階段的回調。是React組件的內置方法。
  4. 最有意思的就是這里了。這樣的寫法會把當前高階組件的全部props和state都發送給CartItem,這樣CartItem就可以取到this.state.seconds屬性的值了。

最后我們就需要修改CartItem組件的內部了。這樣才能輸出this.state.seconds的值。

import React from 'react';

import {IntervalEnhance} from './IntervalEnhance';

class CartItem extends React.Component {

    render() {
        return (
            <article className="row large-4">

                <p className="large-12 column" >
                    <strong>Time elapsed for interval: </strong>
                    {this.props.seconds} ms
                </p>

            </article>
        );
    }
}

注意:全部都完成都不需要修改CartItem組件本身(除了render方法)!這就是為什么High-Order Component為什么這里厲害的原因所在。

##使用ES7裝飾器 使用ES7的裝飾器(decorator)代碼會更加簡潔。

首先,安裝babel-plugin-transform-decorators-legacy:

npm install --save-dev babel-plugin-transform-decorators-legacy

之后,配置*.babelrc*文件:

{
    "presets": ["es2015", "react", "stage-0"],
    "plugins": [
        ["transform-decorators-legacy"]
    ]
}

然后:

import React from 'react';

import {IntervalEnhance} from './intervalEnhance';

@IntervalEnhance
class CartItem extends React.Component {
    // ...略...
}

##總結 Hight-Order Component(高階組件)非常好用,也可以非常有效的解決問題。當前,使用高階組件非常多的用來代替舊的mixin。

有一個典型的例子就是Relay。Relay也是facebook發布的一個完全基於React的framework。你的每一個組件都可以包裹在Relay容器中,自動的存取依賴的數據。


免責聲明!

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



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