1. 程式人生 > >Flux、Redux到react-redux衍變三部曲(一)Flux

Flux、Redux到react-redux衍變三部曲(一)Flux

react開發中,組建直接傳遞引數或者事件都需要props一層層代理,對於複雜元件,它可能巢狀的子元件非常多,層級也比較深,那麼,如果還採用props鏈條來維護元件通訊或者資料共享,將非常困難,也不利於開發和維護。因此,順序地衍生出了Flux、Redux和react-redux,本篇主要介紹Flux。

Flux框架也是一種MVC框架,它採用單向資料流,不允許Model和Control互相引用。Flux框架大致如下:

Views:檢視介面

Action:驅動Dispatcher來觸發狀態變化

Dispatcher:負責分發,關聯Action(接收方)與Store(處理方)

Store:狀態變化的邏輯處理、狀態儲存

通過該Demo大家可以瞭解到Flux的執行機制,那麼直接看程式碼吧,檢視介面 :

// FluxDemo.jsx
import React from 'react';
import FluxView from './FluxView.jsx';
import FluxStore from './FluxStore.js';

class FluxDemo extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			data: FluxStore.getData()
		};
		this.onChange = this.onChange.bind(this);
	}

	componentDidMount() {
		FluxStore.addChangeListener(this.onChange);
	}

	componentWillUnmount() {
		FluxStore.removeChangeListener(this.onChange);
	}

	onChange() {
		const newData = FluxStore.getData();
		this.setState({
			data: newData
		});
	}

	render() {
		return(
			<div>
				<FluxView data={this.state.data}/>
      		        </div>
		);
	}
}

export default FluxDemo;

重點:(1)掛載完成和解除安裝時,要新增/移除store中監聽;(2)傳遞到子元件的狀態必須從store中獲得。這樣子元件中觸發Action後,經過一系列過程最終驅動store裡的狀態變化,意味著傳遞的狀態也跟著變化。

FluxView 元件,該元件主要模擬了通過點選按鈕觸發Action操作:

// FluxView.jsx
import React from 'react';
import FluxAcion from './FluxAcion';

class FluxView extends React.Component {
	constructor(props) {
		super(props);
		this.state = {};
		this.newHandle = this.newHandle.bind(this);
		this.updateHandle = this.updateHandle.bind(this);
	}

	newHandle() {
		FluxAcion.newData("[new action]");
	}

	updateHandle() {
		FluxAcion.updateData("[update action]");
	}

	render() {
		return(
			<div>
				current data is ======= {this.props.data}
				<div>
					<button onClick={this.newHandle}>execute action [New] </button>
					<button onClick={this.updateHandle}>execute action [Update] </button>
					<button>...</button>
				</div>
      		        </div>
		);
	}
}

export default FluxView;

Dispatcher、Action 程式碼如下:

// FluxDispatcher.js
import { Dispatcher } from 'flux';

const FluxDispatcher = new Dispatcher();
export default FluxDispatcher;

// FluxConstants.js
const FluxContants = {
	NEW: 'NEW',
	UPDATE: 'UPDATE'
};

export default FluxContants;

// FluxAcion.js
import FluxConstants from './FluxConstants';
import FluxDispatcher from './FluxDispatcher';

const FluxAcion = {
	newData(data) {
		// Dispatcher 觸發
		FluxDispatcher.dispatch({
			type: FluxConstants.NEW,
			value: data
		});
	},
	updateData(data) {
		// Dispatcher 觸發
		FluxDispatcher.dispatch({
			type: FluxConstants.UPDATE,
			value: data
		});
	}
}

export default FluxAcion;

Action的作用就是驅動Dispatcher,從而分發任務,這時若store只有註冊了Dispatcher監聽,就會收到來自Action的任務。

最後,看看Flux最核心的store:

// FluxStore.js
import { EventEmitter } from 'events';
import FluxDispatcher from './FluxDispatcher';
import FluxConstants from './FluxConstants';

let data = "[default]";

// store 構造
const store = Object.assign({}, EventEmitter.prototype, {
	getData: function() {
		return data;
	},

	emitChange: function() {
		this.emit('change');
	},

	addChangeListener: function(callback) {
		this.on('change', callback);
	},

	removeChangeListener: function(callback) {
		this.removeListener('change', callback);
	}
});

// Dispatcher 註冊
FluxDispatcher.register((action) => {
	switch(action.type) {
		case FluxConstants.NEW:
			data = action.value + "+ 資料操作所需的邏輯處理...";
			store.emitChange();
			break;
		case FluxConstants.UPDATE:
			data = action.value + "+ 資料操作所需的邏輯處理...";
			store.emitChange();
			break;
		default:
			break
	}

});
export default store;

store實現了從Dispatcher處得到資料來源和型別,然後對資料的進行邏輯處理,並向外提供了一個getData()的介面,讓元件可以獲取變化後的狀態資料,最終形成一個閉環,這個模式就是Flux。

通過點選按鈕去驅動[New] Action 和 [update] Action 實現當前data狀態的變化。

Flux有三個缺點:

1. 一個應用可以擁有多個store、action,多個store直接可能有依賴關係。

2. Store封裝了資料和處理資料的邏輯。

3. 使用Flux的元件複用性差,具有Flux元素耦合,不符合react設計思想。

因而,Redux出現了,並通過很巧妙的方式解決了這些缺點。