2.4.1 • Published 6 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,
data
that 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
type
andvalue
. (ex "countup", +1) - emitter event emitter (observer). it's a glue that connects Components and API and Reducer. pass
action
anddata
through emitter, or receive them. - Components ref. yo-yo
- Reducer Reducer takes 2 arguments -
data
andactions value
. it createpartial data to be updated
fromdata
andactions value
. and thenpartial data
is merged withoriginal data
and reflected in Components - API primarily we use
Reducer
to update data, butReducer
is 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 receivesaction
fromComponents
viaemitter
, and passesnew action
- generated through processed inside API - toReducer
viaemitter
.
api
var app = buoyancy(defaultData, opts)
- opts.location - whether to manage the
window.location
. ifwindow.history.pushState
is available it will use that otherwise it will use `window.location.hash.- set to
false
to disable hash
to force using hasheshistory
to 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 -type
andvalue
. passvalue
toemitter
orReducer
(via emitter).type
is "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('/'))