2.4.1 • Published 8 years ago
buoyancy v2.4.1
buoyancy
front-end framework. based yo-yo and simple observer.
features
- data flows one-way. "data down, actions up".
- functional and observer effect.
example
var yo = require('buoyancy/html')
var buoyancy = require('buoyancy')
var app = buoyancy({count: 0}, {location: false})
app.reduce({
count (data, action) {
return {count: data.count + action}
}
})
app.use(emitter => {
emitter.on('countup', e => {
e.stopPropagation()
emitter.emit('count', +1)
})
emitter.on('countdown', e => {
e.stopPropagation()
emitter.emit('count', -1)
})
})
app.route('/', (data, params, u, actionsUp) => yo`
<div>
<button
type="button"
onclick=${e => actionsUp('countup', e)}
>
plus
</button>
<button
type="button"
onclick=${e => actionsUp('countdown', e)}
>
minus
</button>
<div id="result">${data.count}</div>
</div>
`)
document.body.appendChild(app('/'))data flow
+<---------------------------------------------------------------------------------+
| ^
data copied data copied data |
| | | |
v v v |
Components -action-> emitter -action-> (API -action"-> emitter -action"->) Reducer --+- data for rendering. within the application,
datathat you can access is only for reference. It can not be changed directly. (ex "data.count + = 1" can not be done). to change, you only have to use "update function" passed to Reducer - action
typeandvalue. (ex "countup", +1) - emitter event emitter (observer). it's a glue that connects Components and API and Reducer. pass
actionanddatathrough emitter, or receive them. - Components ref. yo-yo
- Reducer Reducer takes 2 arguments -
dataandactions value. it createpartial data to be updatedfromdataandactions value. and thenpartial datais merged withoriginal dataand reflected in Components - API primarily we use
Reducerto update data, butReduceris difficult to work with asynchronous processing. to do asynchronous processing, you need to write an API with an interface that can talk to emitter. as a process, API receivesactionfromComponentsviaemitter, and passesnew action- generated through processed inside API - toReducerviaemitter.
api
var app = buoyancy(defaultData, opts)
- opts.location - whether to manage the
window.location. ifwindow.history.pushStateis available it will use that otherwise it will use `window.location.hash.- set to
falseto disable hashto force using hasheshistoryto force using pushState.
- set to
app.reduce({Reducers})
registers Reducer.
app.reduce({
increment: function incrementReducer (data, action) {
if (typeof action !== 'number') {
throw new TypeError('"increment" action must be "number"')
}
var c = data.count + action
return {count: c}
}
})comppose reducers
var compose = require('buoyancy/compose')
app.reduce(compose({
incrementAndNotify: function (data, action) {
return {count: data.count + action}
}
}, {
incrementAndNotify: function (data, action) {
return {notify: `count up "${action}"`}
}
}))app.use(function(emitter, getData))
when using emitter -primarily asynchronous processing and external API -, will pass the emitter as a function argument. 2nd argument getData function returns copied data.
app.reduce({
'timer:emit' (data, action) {
return {count: action}
}
})
app.use(function (emitter, getData) {
var id
emitter.on('timer:start', function () {
if (id != null) return
id = setInterval(countdwon, 1000)
countdwon()
})
function countdwon () {
var data = getData()
var count = data.count
emitter.emit('timer.emit', count -1)
}
})app.route(routePattern, renderFunction(data, params, route, actionsUp))
register render function
- routePattern see routington
- renderFunction returns
HTML Element. takes 4 arguments -data,params,route,actionsUp. - actionsUp
function. take 2 arguments -typeandvalue. passvaluetoemitterorReducer(via emitter).typeis "event name" receivedemitter.on.
app.route('/', function mainViewRender (data, params, route, actionsUp) {
return html `
<div>
<button onclick=${e => actionsUp('timer:start')}>timer start</button>
<div>${data.count}</div>
</div>
`
})HTMLElement = app(routePath)
app is function. returns a HTML Element. take an argument - routePath
- routePath
urlObject.path
document.body.appendChild(app('/'))