【11】react 之 flux
Flux 是 Facebook 使用的一套前端應用的架構模式。React 標榜自己是 MVC 裏面 V 的部分,那麽 Flux 就相當於添加 M 和 C 的部分。
1.1. Flux介紹
Flux並不是一項新的技術,而是一種架構模式,一個Flux應用由四個部分:
View: 視圖層(組件)
Action(動作):視圖層發出的消息(比如mouseClick)
{ type:’save’, payload:’明天不能休息,自己在家把react弄一弄’ }
Dispatcher(派發器):用來接收Actions、執行回調函數
if(action.type==’save’){ //執行保存代碼。。。。。 store.add(xxxx); store.emit(‘change’); }
Store(數據層):用來存放應用的狀態(數據),一旦發生變動,就提醒Views要更新頁面
Flux 的最大特點:以單向數據流方式支持MVC,Flux執行流程:
1、一個Action由系統或View 層通過用戶交互觸發;
2、Dispatcher 會分發觸發的 Action 給所有註冊的 Store 的回調函數;
3、Store 回調函數根據接收的 Action 更新自身數據之後會觸發一個 change 事件通知 View 數據更改了;
4、View 會監聽這個 change 事件,拿到對應的新數據並調用 setState 更新組件 UI;
Action -> Dispatcher -> Store -> View View->Action -> Dispatcher -> Store -> View
1.2. Flux安裝
npm i flux -save
1.3. Flux View
Flux中的View其實就是React中的組件,與我們以前編寫的組件沒有任何區別。
index.js 入門文件
import React from ‘react‘; import ReactDOM from ‘react-dom‘; import TodoApp from ‘./flux/TodoApp‘; ReactDOM.render( <TodoApp />, document.getElementById(‘app‘) );
TodoApp 主應用組件
import React from ‘react‘; import TextInput from ‘./TextInput‘; import TodoList from ‘./TodoList‘; class TodoApp extends React.Component{ constructor(){ super(); this.state = { datas : [12,123,123] }; } render(){ return ( <div> <TextInput /> <TodoList datas={this.state.datas} /> </div> ); } } export default TodoApp;
TextInput.js 備忘錄輸入框組件
import React from ‘react‘; // 備忘錄,用戶輸入內容,按下回車鍵保存數據 class TextInput extends React.Component{ constructor(){ super(); this.state ={value:""}; } //鍵盤按下回車鍵 _onKeyDown(event){ //判斷是否是回車鍵 if(event.keyCode == 13){ //保存到本地 //清空輸入框 this.setState({ value:"" }); } } _onChange(event){ this.setState({ value:event.target.value }); } render(){ return ( <div> <input type="text" name="username" onChange={this._onChange.bind(this)} onKeyDown={this._onKeyDown.bind(this)} value={this.state.value}/> </div> ); } } export default TextInput;
TodoList.js 備忘錄列表
import React from ‘react‘; class TodoList extends React.Component{ constructor(){ super(); } render(){ var datas = this.props.datas; var lis = datas.map(function(data,index){ return <li key={index}>{data}</li>; }); return ( <ul> {lis} </ul> ); } } export default TodoList;
1.4. Flux Dispatcher
一個應用只需要一個 dispatcher 作為分發中心,管理所有數據流向,分發action給 Store,沒有太多其他的邏輯(一些 action creator 方法也可以放到這裏)。Facebook官方的 Dispatcher 實現輸出一個類,你要寫一個AppDispatcher.js,生成 Dispatcher 實例。
//AppDispatcher.js //Dispatcher分發器,管理所有數據流向,分發動作給 Store。 var Dispatcher = require(‘flux‘).Dispatcher; export default new Dispatcher();
1.5. Flux Action
Action:應用中的一個動作,比如“添加”,“刪除”...
首先要創建動作,通過定義一些 action creator(動作創建者)方法來創建,這些方法用來暴露給外部調用,通過 dispatch 分發對應的動作,所以 action creator 也稱作 dispatcher helper methods 輔助 dipatcher 分發.
TodoActions.js
import React from ‘react‘; import AppDispatcher from ‘./AppDispatcherAppDispatcher‘; var TodoActions = { todoAddItem:function(text){ //創建action動作,然後通過AppDispatcher分發到store進行數據處理 AppDispatcher.dispatch({ actionType : ‘todo_addItem‘, text : text }); }, destroy:function(){ AppDispatcher.dispatch({ actionType : ‘todo_removItem‘ }); } }; export default TodoActions;
有了action creator(動作創造者)我們就可以View中觸發這些動作。
TextInput.js
_onKeyDown(event){ //判斷是否是回車鍵 if(event.keyCode == 13){ //保存到本地(調用action) TodoAction.todoAddItem(this.state.value); //清空輸入框 this.setState({ value:"" }); } }
1.6. Flux Store
Flux四個部分,已經完成了三個,但是現在還沒有地方處理我們的數據。
View:視圖,數據交互(輸入、輸出),觸發動作。
Dispatcher:分發器,把動作發送給響應的Store處理。
Action:動作,描述動作的類型和動作的數據。
Store:管理整個應用的狀態數據(對數據進行實際操作)。
mport {EventEmitter} from ‘events‘; //由於 Store 需要在變動後向 View 發送"change"事件,因此它必須實現事件接口。 //Object.assign 對象拷貝。 多個源對象(第二參數開始對象)的拷貝給目標對象(第一個參數對象) var TodoStore = Object.assign({},EventEmitter.prototype,{ items: [], getData: function() { return this.items; }, addItem: function (text) { this.items.push(text); }, emitChange: function () { this.emit(‘change‘); }, addChangeListener: function(callback) { this.on(‘change‘, callback); }, removeChangeListener: function(callback) { this.removeListener(‘change‘, callback); } }); export default TodoStore; //ListStore.items用來保存條目,ListStore.getAll()用來讀取所有條目,ListStore.emitChange()用來發出一個"change"事件。
最後一步:註冊到 dispatcher,通過動作類型過濾處理當前 Store 關聯的動作
import AppDispatcher from ‘./AppDispatcher‘; //最後一步:註冊到 dispatcher,通過動作類型過濾處理當前 Store 關聯的動作 AppDispatcher.register(function(action){ switch(action.actionType){ case ‘todo_addItem‘: TodoStore.addItem(action.text);//調用Store方法進行數據操作 TodoStore.emitChange();//觸發修改事件,通知view更新狀態 break; } });
1.7. Flux完結
import React from ‘react‘; import TextInput from ‘./TextInput‘; import TodoList from ‘./TodoList‘; import TodoStore from ‘./TodoStore‘ class TodoApp extends React.Component{ constructor(){ super(); this.state = { datas : TodoStore.getData() }; } _onChange(){ his.setState({datas : TodoStore.getData()}); } componentDidMount(){ TodoStore.addChangeListener(this._onChange.bind(this)); } componentWillUnmount(){ TodoStore.removeChangeListener(this._onChange.bind(this)); } render(){ return ( <div> <TextInput /> <TodoList datas={this.state.datas} /> </div> ); } } export default TodoApp;
【11】react 之 flux