ballade v1.2.8
Ballade
Reinterpreted Flux application architecture, for unidirectional data flow in React.
Two version
ballade.js by default, Ballade provides Store is mutable.
ballade.immutable.js it also provides another option, Store is immutable, need dependence immutable-js.
Install
npm
Install ballade using npm.
$ npm install balladeand can be required like this:
var Dispatcher = require('ballade').Dispatcher;Notice: if you want use ballade & immutable, you should install immutable-js.
$ npm install immutableand can be required like this:
var Dispatcher = require('ballade/src/ballade.immutable').Dispatcher;browser
To use ballade from a browser, download js file in dist.
// mutable version
<script src="ballade.js"></script>
<script>
var Dispatcher = Ballade.Dispatcher;
</script>
// immutable version
<script src="immutable.js"></script>
<script src="ballade.immutable.js"></script>
<script>
var Dispatcher = Ballade.Dispatcher;
</script>Architecture Introduction
Store
Store is an storage center of data, provides set and get data interface, just like accessor.
In Views or Controller-views (React Component), can only get data from Store. In Store Callbacks, both of set and get data from Store.
If data changed, Store should publish event for data changes.
There are two types of Store accessor, mutable and immutable, for mutable data and immutable data, respectively by createMutableStore and createImmutableStore method created.
Data stored in Store must configure Schema, make sure the data is valid.
Store has Cache module, be used for data cache. The Cache module integrates localStorage and sessionStorage for persistence cache.
Actions
All of operations, like user interactions or fetch data from server, as long as the data will cause changes in Store, the operation as a Action. The operation that causes the data change can be either set or update data.
If you want change data in Store, can only trigger a Action.
Every Action have includes a unique ActionType and payload, ActionType just like Action unique name, payload data is transfer to Store of data.
Dispatcher
Dispatcher be used for connect Actions and Store, responsible for transfer payload data from Action to specified Store.
Actions Middleware
When transfer payload to Store, middleware can process payload data, each middleware transfer payload data to next middleware when current middleware end processing.
If you want fetch data from server, you can register a middleware.
Store Callbacks
When action is trigger, Store need a callback corresponding with action, use to set data, ActionType corresponding with Store callback name.
API
- Class
- Dispatcher instance
- Store instance
- Others
Ballade.Dispatcher()
Main class use to create a Dispatcher instance.
var Dispatcher = require('ballade').Dispatcher;
var dispatcher = new Dispatcher();Ballade.Schema()
Be used for create a Schema instance.
var Schema = require('ballade').Schema;
var schema1 = new Schema({
str: String,
num: Number,
bol: Boolean,
date: Date,
strArr: [String],
numArr: [Number],
dateArr: [Date],
objArr: [{
name: String,
title: String
}],
anyArr: [],
anyObj: {},
obj: {
votes: Number,
favs: Number,
foo: {
bar: String
}
}
});The Schema used for describe data structure in Store, and validation data, if the data is invalid, then can't stored. View details about Schema documentation.
dispatcher.use(middleware)
middlewareFunction
Register a middleware, all payload of Actions will through the middleware. Middleware can register multiple.
dispatcher.use(function (payload, next) {
// modify payload.count
if (count in payload) {
payload.count++;
}
// must invoke next callback,
// payload through the callback transfer to next middleware
next();
});If you need fetch data from server, you should register a middleware.
dispatcher.use(function (payload, next) {
// payload whether include uri
if (payload.uri) {
fetch(payload.uri, payload.options || {}).then(function(response){
return response.json();
})
.then(function(response){
payload.response = response;
// next callback in a Asynchronous function
next();
});
}
// If not uri, just invoke next callback
else {
next();
}
});dispatcher.createActions(actionCreators)
actionCreatorsObject
Create an group Actions.
var actions = dispatcher.ceateActions({
updateTitle: function (title) {
return {
type: 'example/update-title',
title: title
};
}
});
// trigger a action, and transfer title
actions.updateTitle('foo');Notice: ActionType must be unique, if have duplicate will throw Error. if application is complex, make sure the ActionType is unique, recommend use pseudo namespace. In
example/update-titletheexampleis namaspace.
dispatcher.createMutableStore(schema ,options, callbacks)
schemaSchema instanceoptionsObject optionalcallbacksObject
Create an mutable Store.
schema
Definition an Schema for Store.
var schema = new Schema({
title: String,
meta: {
votes: String,
favs: String
}
});callbacks
Now, let's create exampleStore:
var exampleStore = dispatcher.createMutableStore(schema, {
// This is Store callback
'example/update-title': function (store, action) {
store.set('title', action.title);
}
});The exampleStore be used for Views or Controller-views (React Component), can only get data and subscribe the data changs, can't stored data in Store.
// return title from store
exampleStore.get('title');
// no set method in exampleStore
console.log(exampleStore.set) // => undefinedIn example/update-title callback, store can set and get data if you want.
options
When create an Store instance, also specified by options for Store.
options.errorFunction
If Schema validation data error, will trigger this callback function.
options.error = function (error, store) {
console.log(error.key); // error key
console.log(error.type); // error type
console.log(error.messages); // error message
console.log(store); // Store instance
};options.cacheObjectoptions.cacheObjectoptions.cache[key]The key is same as Schema key.options.cache[key].idString Cache unique id, be used for set or get data from Store.options.cache[key].maxLengthNumber Default value is 20, cache data max length, if length is overflow, then remove the first cache data and stored new cache data.options.cache[key].persistence.typeStringPersistence cache type, supportlocalStorageandsessionStorage。options.cache[key].persistence.prefixStringPersistence cache prefix, add custom prefix make sure the key is unique.
Be used for configure cache for data item in Store, view details about Cache documentation.
dispatcher.createImmutableStore(schema, callbacks)
schemaSchema instanceoptionsObject optionalcallbacksObject
var exampleStore = dispatcher.createImmutableStore(schema, {
// This is Store callback
'example/update-title': function (store, action) {
store.set('title', action.title);
}
});Create an immutable Store, the params usage method same as createMutableStore.
Notice:
createImmutableStoreonly available inballade.immutable.jsand need dependence immutable-js.
store.set(key, value ,pureSet)
keyStringvalueAnythingpureSetBoolean optional
Set data in store, if the key not definition in schema, the set operation should failed. This method will return key.
var key = store.set('title', 'foo');
console.log(key) // => 'title'For mutable Store, support mutable data stored. For immutable Store, support mutable and immutable data stored, there will converted to immutable data, so get data from Store the type is immutable.
If store set data is success, at the same time the store publish data changed event, if pureSet is true, do not publish data change event, default is false.
Notice: set method can only use in Store callback.
store.get(key ,id)
keyStringidString optional
Get data from store, If data is reference type (Object or Array), should return copies of data.
If the key has configure the cache, when get data from Store should specify cache id, if not specify this param, should return all cached data.
var title = store.get('title');
console.log(title) // => 'foo'
// If title is object, title = { foo: 'bar' }
// It return copies of object
var title = store.get('title');
console.log(title.foo) // => 'bar'
title.foo = 'baz';
console.log(title.foo) // => 'baz'
console.log(store.get('title').foo) // => 'bar'Notice: If Store is Immutable type (created by
dispatcher.createImmutableStore), then return data is Immutable type.
store.delete(key ,id)
keyStringidString optional
Delete data from Store.
If the key has configure the cache, when delete data from Store should specify cache id.
store.cleanCache(key)
keyString
Clean cache data from Store.
store.subscribe(type, handler)
typeString optionalhandlerFunction
Subscribe event, type is event type, it is optional, it corresponding with key in Schema. handler is handle function for data changes.
// If title is changed, callback will invoke.
exampleStore.subscribe('title', function (changedValue) {
console.log(changedValue); // should return changed title
});The first argument of handler is changed data, corresponding the changedValue of publish method.
store.unsubscribe(type, handler)
typeString optionalhandlerFunction optional
Cancel subscribe event, type is event type, it is optional. handler is handle function for changes, if type not empty, handler is optional.
exampleStore.unsubscribe('title');store.publish(type, changedValue)
typeStringchangedValueAnything
Broadcast an event, type is event type, it corresponding with key in Schema.
changedValue is used for transmit changed value to event subscriber.
exampleStore.publish('title', 'This is changed title');Ballade.bindStore(Component, store, callbacks)
Bind Store for React Component, the binded Component has receive Store data changes. This method will return a new React Component.
ComponentReact ComponentstoreStore instancecallbacksFunction
var bindStore = require('ballade').bindStore;
App = bindStore(App, todosStore, {
todos: function (value) {
this.setState({
$todos: value
});
}
});In above example, App Component binded todosStore, if todos data in todosStore changes, then will trigger callback function. In the callback function, value is changed data.
And in this function, this pointing Component.
bindStore is easy usage in React Component, in componentDidMount and componentWillUnmount stage of Compoent, don't need bind or unbind data changes event in Store.
Ballade.immutableDeepEqual(Component)
ComponentReact Component
immutableDeepEqual method will optimize shouldComponentUpdate of React Compoent. If the component props or state is Immutable data, only the data is real changed, then trigger render of component. This method will return a new React Component.
var immutableDeepEqual = require('ballade').immutableDeepEqual;
App = immutableDeepEqual(App);Notice: The
immutableDeepEqualmethod only definition inballade.immutable.js.
No waitFor
In Flux, it provides waitFor method use to between dependence Store, this is not good design, it should make application more complex. In flux/examples/flux-chat/js/stores/MessageStore.js, if you remove this code, the example still work.
ChatAppDispatcher.waitFor([ThreadStore.dispatchToken]);Of course, the waitFor not useless in Flux, it make developer more confused.
Dependence between Store in Ballade, just like use a variable, you need make sure variable is available, it is simple.
var storeA = dispatcher.createMutableStore(schema, {
'example/update-title': function (store, action) {
store.set('title', action.title);
}
});
// If storeB dependence storeA
var storeB = dispatcher.createMutableStore(schema, {
'example/update-title': function (store, action) {
var title = storeA.get('title') + '!';
store.set('title', title);
}
});Examples
Test
$ npm install
$ npm testBuild
$ npm install
$ npm run buildThanks
License
MIT @ Yiguo Chen
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago