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出現了,並通過很巧妙的方式解決了這些缺點。