A Flux unidirectional data flow state machine is implemented on KNOCKOUTJS, which mainly solves the problem of coupling data between multiple components.
First, in fact, simple
Flux design concept and implementation, to a large extent, and reference to the implementation of VUEX, but simplifies some processes, the data flow diagram is as follows:
From, to see that the change in data is one-way loop. I think this is the core of the flux concept. The action specification in VUEX is action and mutation, and the action to trigger Mutation,action can be asynchronous, while mutation is synchronous update. While I was designing KO's flux, I removed the mutation, because I understand that asynchronous requests are generally related to API interfaces, which have great variability and should be differentiated from the business or project architecture.
Second, if you use
Of course, flux is only for Knockoutjs, so you must introduce KNOCKOUTJS before you use it. The main methods and objects of flux
2.1 Static methods
Method |
Description |
Flux.use |
In require mode, the method of associating flux with Ko, of course, must first be called with the CreateStore method. |
Flux.createstore |
Create a store (state) instance, of course, this method has a return value, and his return value can be called by the Register method on the specified domain, but the first time this method is called is to create a rootstore (root state), which he does not allow to be registered to the domain. |
2.1.1 Flux.createstore parameter format
Parameter name |
Description |
State |
State-related state data |
Actions |
Change the State method on the states, the first parameter of the method is the key, the second parameter is the incoming related content |
Getters |
Gets the state-related status data, and of course returns is a KO monitor object. |
2.2 Example methods
The execution of the CreateStore method adds the $store property on the KO instance, which is an instance object of the state, and can be called from anywhere to trigger the event by his dispatch.
Method |
Description |
Register |
Create and register a state field, where the domain and domain are stored independently of each other, and the action or get names can be duplicated between domains |
UnRegister |
Remove a State field |
Dispatch |
The specified action is called according to ActionName, no return value |
Get |
A return value of the specified get, based on the getname call |
Third, the simple use
This example defines four KO bound areas, namely: App1, App2, APP3, App4. Implementing the change to name in APP4 automatically affects the App1, and app3 changes to the list automatically affect the APP2.
3.1 Defining a VM and initializing the store
functionViewModel () { This. List =Ko.observablearray (); This. Name = ko.observable (' Anonymous '); This. Count = ko.computed (function(){ //must be used this time, KO. $store has not been created yet, it should be executed once ko.computed is created. //If the child VM relies on the primary VM, it can still be used with KO. $store return This. List (). length + ' number ';//the monitoring object needs to be evaluated, otherwise the computed will not be valid}, This);}varFULLVM =NewViewModel ();varindex = 1; FULLVM.VF={add:function() {ko. $store. Dispatch (' AddClass ', {title: ' title ' + (index++)}); }}varopt ={state: {CLASS:FULLVM}, actions:{"SetName":function(State, name) {state.class.name (name); }, "AddClass":function(State, ClassInfo) {State.class.list.push (ClassInfo); }}, getters:{"GetName":function(state) {returnState.class.name; }}}flux.createstore (opt);
Based on the above code, a class of ViewModel is defined first, an instance of the FULLVM is created, and the Add method is added directly to the FULLVM instance.
The state of opt refers to FULLVM, which also configures the actions and getters related objects and then calls the Flux.createstore (opt) method. Create a store and associate it to the KO. $store object.
3.2 Binding to Views
HTML code:
<DivID= "App1">App1:<spanData-bind= "Text:ko. $store. Get (' GetName ')"></span></Div><DivID= "APP4">APP4:<inputtype= "text"Data-bind= "Value:name" /> <Buttontype= "text"Data-bind= "Click:changename" >Change the name</Button> <spanData-bind= "Text:ko. $store. State.class.name"></span></Div><HR><DivID= "App2">APP2:<ulData-bind= "Foreach:list" > <LiData-bind= "Text:title" ></Li> </ul></Div><DivID= "APP3">APP3:<Buttontype= "button"Data-bind= "Click:vf.add" >Add to</Button> <spanData-bind= "Text:count"></span></Div>
JS Code:
var app1 = ko.applybindings (FULLVM, document.getElementById ("App1")); var app2 = ko.applybindings (FULLVM, document.getElementById ("App2")); var app3 = ko.applybindings (FULLVM, document.getElementById ("APP3")); // testing for dependency decoupling between two VMS var app4 = ko.applybindings ({ name:ko.observable (), changename:function (data,event) { ko. $store. Dispatch (this. Name ());} , document.getElementById ("APP4"));
Iv. Examples of domains
HTML code:
<DivID= "App1"> <spanData-bind= "Text:name" ></span></Div><DivID= "App2"> <spanData-bind= "Text:name"></span> <spanData-bind= "Text:full"></span> <Buttontype= "button"Data-bind= "Click:changename" >Change name</Button></Div>
JS Code:
functionRootviewmodel () { This. Name = ko.observable (' root '); }varRVM =NewRootviewmodel (); Flux.createstore ({STATE:RVM});//creating a root state devicevarTreenode={name:ko.observable (' Node '), ChangeName:function() {ko. $store. Areas.treeNode.state.name (' New name '); }, Full:ko.computed (function(){ //Computed's duties: 1. Monitor the changes of other object properties, and affect their own objects (flux resolution); 2. Merging several properties of its own objects (under function, this is solvable) //cannot access the object itself through KO. $store because the first object itself is not initialized well varstore =Ko. $store; //(Store.areas.treeNode? Store.areas.treeNode.state.name (): ") This is also not possible, because the first time to solve, but the back certainly not returnStore.state.name (); })}ko. $store. Register (' TreeNode ', Flux.createstore ({state:treenode}));//creating a sub-state machinevarApp1 = Ko.applybindings (RVM, document.getElementById ("App1"));varAPP2 = Ko.applybindings (TreeNode, document.getElementById ("app2"));
In fact, it is very simple to first create a RVM (that is, the root state), and then call the Register method on the root state to register a sub-state (that is, the domain). ko.$store === rVM
, that is to say KO. $store is the root state device.
V. Other
- Of course, the modular reference is also supported. Specific instance details can be found in the test sample in testing.
- Git address of the project: Https://gitee.com/ko-plugins/flux.git, Welcome to correct and put forward valuable comments .
Knockoutjs on its own implementation of flux