Loxe
Flux architecture incorporates FRP library implementation. Observable is awesome!
- The main purpose is mapping the Observables to props of the component
- Design with a focus on ES6-7.
- Using the Higher-order Components with decorator instead of Mixin.
- To follow the ES Observable Proposal to the
Subject
. - Wherever possible, declarative statements should be.
Installation
Recommend for use browserify, or other CommonJS/ES6 modules resolver.
Use browserify
To install the loxe
by NPM.
npm install --save loxe
// CommonJSvar Loxe = ; // ES6 modules (babel);
# Loxe depends on React. If you want to separate `react` as other bundle. browserify index.js -x react -o bundle.jsbrowserify -r react -o libs.js
<script src="loxe.js">
Use loxe.js
built with browserify-shim. To run the Loxe window.React
is required.
Usage
Flux comparison example
Minimal Example
Domain
that manages the Store
and Action
. Each feature of Flux provides to Component
, using the Context feature of the React.
Loxe uses javascript-decorators for the component. TypeScript or Babel with --stage 1
option, use recommended. (As a function Root = provideContext(Root);
you might also use)
; { // Object returns that will provide to components, through `@provideObservables`. return items$ : thisitems$ count$ : thisitems$ ; } { // `.publish()` is like a dispatch of the Flux. // By event name published here, you can subscribe from the Store. this; } { super; // init data storage property this_items = ; // create Observable that keep latest value. (like `Rx.BehaviorSubject`) thisitems$ = Subject; // `.plugStream$` is Observable, and `{event: string, payload: any}` // will be published from the `Action` will be aggregated. // `.subscribeEvent(event, observer)` subscribe to Observable // that from plugStream filtered by events. this; } // Becoming a root Component, `@provideContext` Decorator is required.// It connects components Tree Root and Flux.@Component { return <Child />; } // @provideAction: Inject Action instance to the component props.// @provideObservables: Value of the Observable will be provided// from the domain mapped to the props.@@Component { thispropsAppAction; } { return <div> <button onClick=thisaddItem>add item</button> <ul> thispropsitems </ul> </div> ; } const appDomain = ;appDomain;appDomain;appDomain;
Choose FRP library
At first, you MUST sets the FRP (Functional Reactive Programming) library, used internally by the Subject
.
;;; Subject;Subject;
Supported Reactive-Extensions/RxJS and rpominov/kefir.
;;; Subject;Subject;
This is a transitional period for the future within fixed on either side.
API Reference
Action
Is the Action
of the flux. Implements the API from component to use imperative.
eventStream$: Subject
All events will be published through this stream. During the initialization phase of the Domain
, is connected with the Store#plugStream$
.
publish(event: string, payload: any)
Publish event data. It's a this.eventStream$.next({event, payload})
an equivalent process.
do(event: string, payload: any)
Alias of publish()
.
Domain
Domain
that manages the Store
and Action
. Each feature of Flux provides to Component
, using the context of the React.
registerAction(action: Action)
Register Action
instance.
registerStore(store: Store)
Register Store
instance.
mountRootComponent(root: Component, container: Element)
Mount root component at node, and connect domain contexts as props. root
Component should applied @provideContext
decorator.
getObservables(): object
This method called '@provideObservables'. You need to maintain their own when returning this object is not cached, so consistently reuses.
{ if !thisobservables$ thisobservables$ = items$ : thisitems$ count$ : thisitems$ ; return thisobservables$;}
Store
Is the Store
of the flux. Store
some Observable publishes the Domain
.
plugStream$: Subject
plugStream$
is Observable, and {event: string, payload: any}
will be published from the Action
will be aggregated.
Without subscribing to it directly, usually using either of the following methods.
getEvent(event: string): Observable
subscribe(target: Observable, callback: Function)
subscribeEvent(event: string, callback: Function)
These methods generate an Observable filtered in any event from the plugStream$
or, to subscribe to it. Look at the following example.
// example { super; // You want to combine multiple events useful 'getEvent()'. let foo$ = this; let bar$ = this; this; // 'subscribeEvent()' useful if you only subscribe to one type of event. this;}
Subject
Creates an object with both Observable and Observer roles. That object behave like Rx.BehaviorSubject
, Bacon.Bus
, and Kefir.Bus
(deprecated).
Objects that are generated by subject can be used on the function of next()
. Useful when combining multiple event streams, controlling the UI.
{ thisclickStream$ = Subject; thisclickStream$;} { return <button onClick=thisclickStream$>click me</button>;}
Subject.setBuilder(builder: Rxbuilder|KefirBuilder)
Set instance of Subject.RxBuilder
or Subject.KefirBuilder
. Select FRP library you want to use.
Subject.setCombineTemplate(combineTemplate: Function)
Set function of rx.observable.combinetemplate or kefir.combinetemplate. Use when mapping the Observables to prop of the component.
Subject.stream(): Subject
To create standard Subject
object. Value issued only after starting to subscribe.
let stream$ = Subject;stream$next100;stream$;stream$next200; // => Log: 200
Subject.property(): Subject
To create Subject
object that keeps latest value. Latest value is issued immediately when started to subscribe.
let property$ = Subject;property$next100;property$;property$next200; // => Log: 100// => Log: 200
next(value: any)
A common interface with the subject. Notifies the subject of a new element in the sequence.
throw(error: Error)
A common interface with the subject. Notifies the subject that an error has occurred.
return()
A common interface with the subject. Notifies the subject of the end of the sequence.
Providers
Providers are implemented as decorators. But also support to normally functional use.
// decorators@Component // normally functionComponent MyComponent = ;
@provideContext()
@provideContext
provides getAction()
and getObservables()
from props.domain
in the context of the React.Component.
These methods are used in the @provideAction
or @provideObservables
, component tree and Store
and the Action
is associated.
@provideActions(Actions: Action[])
Inject Action instance to the component props.
@Component { thispropsFooAction; } { thispropsBarAction; }
@provideObservables
Value of the Observable will be provided from the Domain
mapped to the this.props
.
@Component { return <ul> thispropsitems </ul> <p>count: thispropscount</p> <p>current: thispropsnavigatecurrent</p> <p>prev: thispropsnavigateprev</p> <p>next: thispropsnavigatenext</p> ; }
@provideSideEffect()
Components that use this Decorator is to control the adverse effects of global available props
@Component static { let someOneVisible = propsList; let htmlElement = documentbodyparentNode; if someOneVisible htmlElementclassList; else htmlElementclassList; }
Tests
npm install
npm test
Contributing
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
License
MIT