In react, flux is a public state management solution, which is used to build the application architecture of client-side web applications and manage public state in the form of one-way flow of data.
The operating environment of this tutorial: Windows7 system, react17.0.1 version, Dell G3 computer.
What is flux
flux is a public state management solution similar to vuex in react. It is officially used by Facebook Build the application architecture of the client web application and manage the public status by using the one-way flow of data.
It is more like a pattern than a formal framework. Developers can quickly get started with Flux without requiring too much new code.
Use cnpm i flux -S
to install.
Composition of flux
View: View layer
Action : Message sent by the view
Dispatcher: Dispatcher, used to receive Action and execute callback function
Store: Data layer, storage state, Once changes occur,
flux’s workflow
The biggest feature of Flux is the "one-way flow" of data.
User accesses View
View issues user’s Action
Dispatcher receives Action and requests Store performs corresponding updates
After Store is updated, a "change" event is issued
View After receiving the "change" event, the page is updated
In the above process, data always flows "one-way", and "two-way flow" of data will not occur in any adjacent part. This ensures clarity of the process.
After reading this, you may feel confused, OK, this is normal. Next, I will explain each step in detail.
Please open the Demo homepageindex.jsx
, you will see that only one component is loaded.
// index.jsx var React = require('react'); var ReactDOM = require('react-dom'); var MyButtonController = require('./components/MyButtonController'); ReactDOM.render( <MyButtonController/>, document.querySelector('#example') );
In the above code, you may have noticed that the name of the component is not MyButton
, but MyButtonController
. why is that?
Here, I use React’s controller view mode. The "controller view" component is only used to save state and then forward it to child components. The source code of MyButtonController
is very simple.
// 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;
In the above code, MyButtonController
passes the parameters to the sub-component MyButton
. The source code for the latter is even simpler.
// components/MyButton.jsx var React = require('react'); var MyButton = function(props) { return <div> <button onClick={props.onClick}>New Item</button> </div>; }; module.exports = MyButton;
In the above code, you can see that MyButton
is a pure component (that is, it does not contain any state), which facilitates testing and reuse. This is the biggest advantage of the "control view" mode.
MyButton
There is only one logic, that is, once the user clicks, the this.createNewItem
method is called to send an Action to the Dispatcher.
// components/MyButtonController.jsx // ... createNewItem: function (event) { ButtonActions.addNewItem('new item'); }
In the above code, calling the createNewItem
method will trigger an Action named addNewItem
.
Each Action is an object, containing an actionType
attribute (describing the type of action) and some other attributes (used to pass data).
In this Demo, the ButtonActions
object is used to store all Actions.
// actions/ButtonActions.js var AppDispatcher = require('../dispatcher/AppDispatcher'); var ButtonActions = { addNewItem: function (text) { AppDispatcher.dispatch({ actionType: 'ADD_NEW_ITEM', text: text }); }, };
In the above code, the ButtonActions.addNewItem
method uses AppDispatcher
to dispatch the action ADD_NEW_ITEM
to the Store.
The function of Dispatcher is to dispatch Action to Store. You can think of it as a router, responsible for establishing the correct delivery route for Actions between View and Store. Note that there can only be one Dispatcher and it is global.
Facebook’s official Dispatcher implementation outputs a class. You need to write an AppDispatcher.js
to generate a Dispatcher instance.
// dispatcher/AppDispatcher.js var Dispatcher = require('flux').Dispatcher; module.exports = new Dispatcher();
AppDispatcher.register()
method is used to register various Action callback functions.
// 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 } })
In the above code, Dispatcher receives the ADD_NEW_ITEM
action and will execute the callback function to operate ListStore
.
Remember, Dispatcher is only used to dispatch Actions and should not have other logic.
Store saves the state of the entire application. Its role is a bit like Model in MVC architecture.
In our Demo, there is a ListStore
, where all data is stored.
// 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;
In the above code, ListStore.items
is used to save items, ListStore.getAll()
is used to read all items, ListStore.emitChange( )
Used to emit a "change" event.
Since the Store needs to send a "change" event to the View after a change, it must implement the event interface.
// 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); } });
上面代码中,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视频教程》
The above is the detailed content of What does flux mean in react?. For more information, please follow other related articles on the PHP Chinese website!