Heim > Artikel > Web-Frontend > Was bedeutet Fluss in Reaktion?
In React ist Flux eine Lösung zur öffentlichen Zustandsverwaltung, die zum Aufbau der Anwendungsarchitektur clientseitiger Webanwendungen und zur Verwaltung des öffentlichen Zustands in Form eines unidirektionalen Datenflusses verwendet wird.
Die Betriebsumgebung dieses Tutorials: Windows 7-System, Reaktionsversion 17.0.1, Dell G3-Computer.
Was ist Flux? Flux ist eine öffentliche Zustandsverwaltungslösung, die Vuex in React ähnelt. Es handelt sich um die von Facebook offiziell bereitgestellte Anwendungsarchitektur zum Erstellen von Client-Webanwendungen unter Verwendung des einseitigen Datenflusses Manage öffentlicher Status in Form von
.Es ähnelt eher einem Muster als einem formalen Framework. Entwickler können schnell mit Flux beginnen, ohne zu viel neuen Code zu benötigen.
Verwenden Sie zur Installationcnpm i flux -S
.
cnpm i flux -S
的方式进行安装。
flux的组成
View:视图层
Action:视图发出的消息
Dispatcher:派发者,用来接收Action,执行回调函数
Store:数据层,存放状态,一旦发生改动,
flux的工作流程
Flux 的最大特点,就是数据的"单向流动"。
用户访问 View
View 发出用户的 Action
Dispatcher 收到 Action,要求 Store 进行相应的更新
Store 更新后,发出一个"change"事件
View 收到"change"事件后,更新页面
上面过程中,数据总是"单向流动",任何相邻的部分都不会发生数据的"双向流动"。这保证了流程的清晰。
读到这里,你可能感到一头雾水,OK,这是正常的。接下来,我会详细讲解每一步。
请打开 Demo 的首页index.jsx
,你会看到只加载了一个组件。
// index.jsx var React = require('react'); var ReactDOM = require('react-dom'); var MyButtonController = require('./components/MyButtonController'); ReactDOM.render( <MyButtonController/>, document.querySelector('#example') );
上面代码中,你可能注意到了,组件的名字不是 MyButton
,而是 MyButtonController
。这是为什么?
这里,我采用的是 React 的 controller view 模式。"controller view"组件只用来保存状态,然后将其转发给子组件。MyButtonController
的源码很简单。
// components/MyButtonController.jsx var React = require('react'); var ButtonActions = require('../actions/ButtonActions'); var MyButton = require('./MyButton'); var MyButtonController = React.createClass({ createNewItem: function (event) { ButtonActions.addNewItem('new item'); }, render: function() { return <MyButton onClick={this.createNewItem} />; } }); module.exports = MyButtonController;
上面代码中,MyButtonController
将参数传给子组件MyButton
。后者的源码甚至更简单。
// components/MyButton.jsx var React = require('react'); var MyButton = function(props) { return <div> <button onClick={props.onClick}>New Item</button> </div>; }; module.exports = MyButton;
上面代码中,你可以看到MyButton
是一个纯组件(即不含有任何状态),从而方便了测试和复用。这就是"controll view"模式的最大优点。
MyButton
只有一个逻辑,就是一旦用户点击,就调用this.createNewItem
方法,向Dispatcher发出一个Action。
// components/MyButtonController.jsx // ... createNewItem: function (event) { ButtonActions.addNewItem('new item'); }
上面代码中,调用createNewItem
方法,会触发名为addNewItem
的Action。
每个Action都是一个对象,包含一个actionType
属性(说明动作的类型)和一些其他属性(用来传递数据)。
在这个Demo里面,ButtonActions
对象用于存放所有的Action。
// actions/ButtonActions.js var AppDispatcher = require('../dispatcher/AppDispatcher'); var ButtonActions = { addNewItem: function (text) { AppDispatcher.dispatch({ actionType: 'ADD_NEW_ITEM', text: text }); }, };
上面代码中,ButtonActions.addNewItem
方法使用AppDispatcher
,把动作ADD_NEW_ITEM
派发到Store。
Dispatcher 的作用是将 Action 派发到 Store、。你可以把它看作一个路由器,负责在 View 和 Store 之间,建立 Action 的正确传递路线。注意,Dispatcher 只能有一个,而且是全局的。
Facebook官方的 Dispatcher 实现输出一个类,你要写一个AppDispatcher.js
,生成 Dispatcher 实例。
// dispatcher/AppDispatcher.js var Dispatcher = require('flux').Dispatcher; module.exports = new Dispatcher();
AppDispatcher.register()
方法用来登记各种Action的回调函数。
// dispatcher/AppDispatcher.js var ListStore = require('../stores/ListStore'); AppDispatcher.register(function (action) { switch(action.actionType) { case 'ADD_NEW_ITEM': ListStore.addNewItemHandler(action.text); ListStore.emitChange(); break; default: // no op } })
上面代码中,Dispatcher收到ADD_NEW_ITEM
动作,就会执行回调函数,对ListStore
进行操作。
记住,Dispatcher 只用来派发 Action,不应该有其他逻辑。
Store 保存整个应用的状态。它的角色有点像 MVC 架构之中的Model 。
在我们的 Demo 中,有一个ListStore
,所有数据都存放在那里。
// stores/ListStore.js var ListStore = { items: [], getAll: function() { return this.items; }, addNewItemHandler: function (text) { this.items.push(text); }, emitChange: function () { this.emit('change'); } }; module.exports = ListStore;
上面代码中,ListStore.items
用来保存条目,ListStore.getAll()
用来读取所有条目,ListStore.emitChange()
Flusszusammensetzung
index.jsx
und Sie werden sehen, dass nur eine Komponente geladen ist. 🎜// stores/ListStore.js var EventEmitter = require('events').EventEmitter; var assign = require('object-assign'); var ListStore = assign({}, EventEmitter.prototype, { items: [], getAll: function () { return this.items; }, addNewItemHandler: 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); } });🎜Im obigen Code ist Ihnen vielleicht aufgefallen, dass der Name der Komponente nicht
MyButton
, sondern MyButtonController
ist. Warum ist das so? 🎜🎜Hier verwende ich den Controller-Ansichtsmodus von React. Die Komponente „Controller-Ansicht“ dient nur dazu, den Zustand zu speichern und ihn dann an untergeordnete Komponenten weiterzuleiten. Der Quellcode von MyButtonController
ist sehr einfach. 🎜// components/MyButtonController.jsx var React = require('react'); var ListStore = require('../stores/ListStore'); var ButtonActions = require('../actions/ButtonActions'); var MyButton = require('./MyButton'); var MyButtonController = React.createClass({ getInitialState: function () { return { items: ListStore.getAll() }; }, componentDidMount: function() { ListStore.addChangeListener(this._onChange); }, componentWillUnmount: function() { ListStore.removeChangeListener(this._onChange); }, _onChange: function () { this.setState({ items: ListStore.getAll() }); }, createNewItem: function (event) { ButtonActions.addNewItem('new item'); }, render: function() { return <MyButton items={this.state.items} onClick={this.createNewItem} />; } });🎜Im obigen Code übergibt
MyButtonController
Parameter an die Unterkomponente MyButton
. Der Quellcode für Letzteres ist noch einfacher. 🎜// components/MyButton.jsx var React = require('react'); var MyButton = function(props) { var items = props.items; var itemHtml = items.map(function (listItem, i) { return <li key={i}>{listItem}</li>; }); return <div> <ul>{itemHtml}</ul> <button onClick={props.onClick}>New Item</button> </div>; }; module.exports = MyButton;🎜Im obigen Code können Sie sehen, dass
MyButton
eine reine Komponente ist (das heißt, sie enthält keinen Status), was das Testen und die Wiederverwendung erleichtert. Dies ist der größte Vorteil des Modus „Kontrollansicht“. 🎜🎜MyButton
hat nur eine Logik, nämlich die Methode this.createNewItem
aufzurufen, sobald der Benutzer darauf klickt, und eine Aktion an den Dispatcher zu senden. 🎜rrreee🎜Im obigen Code löst der Aufruf der Methode createNewItem
eine Aktion namens addNewItem
aus. 🎜actionType
-Attribut (das den Aktionstyp beschreibt) und einige andere Attribute (die zur Datenübergabe verwendet werden) enthält. 🎜🎜In dieser Demo wird das ButtonActions
-Objekt zum Speichern aller Aktionen verwendet. 🎜rrreee🎜Im obigen Code verwendet die Methode ButtonActions.addNewItem
AppDispatcher
, um die Aktion ADD_NEW_ITEM
an den Store zu senden. 🎜AppDispatcher.js
schreiben, um eine Dispatcher-Instanz zu generieren. Die Methode 🎜rrreee🎜AppDispatcher.register()
wird zum Registrieren verschiedener Aktionsrückruffunktionen verwendet. 🎜rrreee🎜Wenn der Dispatcher im obigen Code die Aktion ADD_NEW_ITEM
empfängt, führt er die Rückruffunktion aus und betreibt ListStore
. 🎜🎜Denken Sie daran, dass der Dispatcher nur zum Versenden von Aktionen verwendet wird und keine andere Logik haben sollte. 🎜ListStore
, in dem alle Daten gespeichert sind. 🎜rrreee🎜Im obigen Code wird ListStore.items
zum Speichern von Elementen verwendet, ListStore.getAll()
wird zum Lesen aller Elemente verwendet, ListStore.emitChange( ) wird verwendet, um ein „Änderungs“-Ereignis auszulösen. 🎜🎜Da der Store nach der Änderung das Ereignis „Änderung“ an die Ansicht senden muss, muss er die Ereignisschnittstelle implementieren. 🎜<pre class="brush:js;toolbar:false;">// stores/ListStore.js
var EventEmitter = require(&#39;events&#39;).EventEmitter;
var assign = require(&#39;object-assign&#39;);
var ListStore = assign({}, EventEmitter.prototype, {
items: [],
getAll: function () {
return this.items;
},
addNewItemHandler: function (text) {
this.items.push(text);
},
emitChange: function () {
this.emit(&#39;change&#39;);
},
addChangeListener: function(callback) {
this.on(&#39;change&#39;, callback);
},
removeChangeListener: function(callback) {
this.removeListener(&#39;change&#39;, callback);
}
});</pre><p>上面代码中,<code>ListStore
继承了EventEmitter.prototype
,因此就能使用ListStore.on()
和ListStore.emit()
,来监听和触发事件了。
Store 更新后(this.addNewItemHandler()
)发出事件(this.emitChange()
),表明状态已经改变。 View 监听到这个事件,就可以查询新的状态,更新页面了。
现在,我们再回过头来修改 View ,让它监听 Store 的 change
事件。
// components/MyButtonController.jsx var React = require('react'); var ListStore = require('../stores/ListStore'); var ButtonActions = require('../actions/ButtonActions'); var MyButton = require('./MyButton'); var MyButtonController = React.createClass({ getInitialState: function () { return { items: ListStore.getAll() }; }, componentDidMount: function() { ListStore.addChangeListener(this._onChange); }, componentWillUnmount: function() { ListStore.removeChangeListener(this._onChange); }, _onChange: function () { this.setState({ items: ListStore.getAll() }); }, createNewItem: function (event) { ButtonActions.addNewItem('new item'); }, render: function() { return <MyButton items={this.state.items} onClick={this.createNewItem} />; } });
上面代码中,你可以看到当MyButtonController
发现 Store 发出 change
事件,就会调用 this._onChange
更新组件状态,从而触发重新渲染。
// components/MyButton.jsx var React = require('react'); var MyButton = function(props) { var items = props.items; var itemHtml = items.map(function (listItem, i) { return <li key={i}>{listItem}</li>; }); return <div> <ul>{itemHtml}</ul> <button onClick={props.onClick}>New Item</button> </div>; }; module.exports = MyButton;
推荐学习:《react视频教程》
Das obige ist der detaillierte Inhalt vonWas bedeutet Fluss in Reaktion?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!