淺說Flux開發

來源:互聯網
上載者:User

標籤:

淺說Flux開發

前段時間,寫了篇關於React的檔案:React:組件的生命週期,比較詳細的說了下React組件的生命週期。

說道 React,很容易可以聯想到 Flux。今天以 React 介紹及實踐教程 一文中的demo為樣本,簡單說說 Flux 的開發方式。

Flux是什麼

Flux 是 Facebook 使用者建立用戶端 Web 應用程式的前端架構, 它通過利用一個單向的資料流補充了 React 的複合檢視組件。

Flux 的設計架構

Flux 架構有三個主要部分:Dispatcher 、Store 和View(React 組件)。Store 包含了應用的所有資料,Dispatcher 負責調度,替換了 MVC中 的Controller,當 Action 觸發時,決定了 Store 如何更新。當 Store變化後,View 同時被更新,還可以產生一個由Dispatcher 處理的Action。這確保了資料在系統組件間單向流動。當系統有多個 Store 和 View 時,仍可視為只有一個 Store 和一個 View,因為資料只朝一個方向流動,並且不同的 Store 和 View 之間不會直接影響彼此。

Flux的簡單開發

在顏色盤的demo中,對介面的組件劃分是這樣的:

使用者在 ColorPanel(View) 上產生一個 Action,Action 將資料流轉到 Dispatcher,Dispatcher 根據 Action 傳遞的資料更新 Store,當 Store變化後,View 同時被更新。

(若你要擷取本文的原始碼,可以戳此:Flux-Demo)

Store

Store 包含了應用的所有資料,並負責更新 View(ColorPanel),為簡單,簡化 Store 的定義:

let EventEmitter = require(‘events‘).EventEmitter;let emitter = new EventEmitter();export let colorStore = {    colorId: 1,    listenChange(callback){        emitter.on(‘colorChange‘, callback);    },    getColorId(){        return this.colorId    },    setColorId(colorId){        this.colorId = colorId;        emitter.emit(‘colorChange‘);    }};
Dispatcher

Action 要靠 Dispatcher 去調度,才能更新 Store,並有 Store 去更新對應的 View 組件。定義一個 colorDispatcher 用於調度:

import {Dispatcher} from ‘flux‘;import {colorStore} from ‘./colorStore‘;export let colorDispatcher = new Dispatcher();colorDispatcher.register((payload) => {    switch (payload.action){        case ‘CHANGE_COLOR_ID‘:            colorStore.setColorId(payload.colorId);            break;    }});
Action

當滑鼠懸浮在 ColorBar 中的一個色塊時,根據色塊 ID 的變化,ColorDisplay 顯示對應的顏色。我們定義一個 Action 為 CHANGE_COLOR_ID:

import {colorDispatcher} from ‘./colorDispatcher‘;export let colorAction = {    changeColorId(colorId){        colorDispatcher.dispatch({            action: ‘CHANGE_COLOR_ID‘,            colorId: colorId        })    }};

建議定義的 Action 符合 FSA 規範。

View

按照的組件劃分,我們渲染出介面:

ColorDisplay:

import React, {Component} from ‘react‘;class ColorDisplay extends Component {    shouldComponentUpdate(nextProps, nextState){        return this.props.selectedColor.id !== nextProps.selectedColor.id;    }    render(){        return (            <div className = ‘color-display‘>                <div className = {this.props.selectedColor.value}>                    {this.props.selectedColor.title}                </div>            </div>        )    }}export default ColorDisplay;

ColorBar:

import React, {Component} from ‘react‘;import {colorAction} from ‘../flux/colorAction‘;import {colorStore} from ‘../flux/colorStore‘;class ColorBar extends Component {    handleHover(colorId){        let preColorId = colorStore.getColorId();        if(preColorId != colorId){            colorAction.changeColorId(colorId);        }    }    render(){        return (            <ul>                {/* Reaact中迴圈渲染元素時, 需要用key屬性確保正確渲染, key值唯一*/}                {this.props.colors.map(function(color){                    return (                        <li key = {color.id}                            onMouseOver = {this.handleHover.bind(this, color.id)}                            className = {color.value}>                        </li>                    )                }, this)}            </ul>        )    }}export default ColorBar;

ColorPanel:

import React, {Component} from ‘react‘;import ColorDisplay from ‘./colorDisplay‘;import ColorBar from ‘./colorBar‘;import {colorStore} from ‘../flux/colorStore‘class ColorPanel extends Component {    constructor(props){        super(props);        this.state = {            selectedColor: this.getSelectedColor(colorStore.getColorId())        };        colorStore.listenChange(this.onColorHover.bind(this));    }    getSelectedColor(colorId){        if(! colorId){            return null        }        let length = this.props.colors.length;        let i;        for(i = 0; i < length; i++) {            if(this.props.colors[i].id === colorId){                break;            }        }        return this.props.colors[i];    }    shouldComponentUpdate(nextProps, nextState){        return this.state.selectedColor.id !== nextState.selectedColor.id;    }    render(){        return (            <div>                <ColorDisplay selectedColor = {this.state.selectedColor} />                <ColorBar colors = {this.props.colors}  />            </div>        )    }    onColorHover(){        let colorId = colorStore.getColorId();        this.setState({            selectedColor: this.getSelectedColor(colorId)        })    }}ColorPanel.defaultProps = {    colors: [        {id: 1, value: ‘red‘, title: ‘red‘},        {id: 2, value: ‘blue‘, title: ‘blue‘},        {id: 3, value: ‘green‘, title: ‘green‘},        {id: 4, value: ‘yellow‘, title: ‘yellow‘},        {id: 5, value: ‘pink‘, title: ‘pink‘},        {id: 6, value: ‘black‘, title: ‘black‘}    ]};export default ColorPanel;

App:

var ReactDom = require(‘react-dom‘);import React from ‘react‘;import ColorPanel from ‘./panel/colorPanel‘;require(‘./app.css‘);window.onload = function () {    ReactDom.render(<ColorPanel />, document.getElementById(‘demos‘));}

最終的的介面如下:

總結

本文簡單的說了下如何利用 Flux 去開發實際應用,對於負載要求不高的應用,Flux 是完全可以使用的,複雜的富應用則可以藉助 Redux + React 構建,Redux 負責資料分發和管理,其資料流的可控性比 Flux 更強,React 則依舊負責 View,但二者並不能直接連接,需要依賴 react-redux。

若你要擷取本文的原始碼,可以戳此:Flux-Demo

原文出處:http://www.ido321.com/1658.html

淺說Flux開發

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.