Add documentation on components (#673)

* Add documentation on components

* Fix typo
This commit is contained in:
Carl Törnqvist
2018-07-10 14:40:51 +02:00
committed by Yoshua Wuyts
parent 0650e642d4
commit 65d124b352
+100
View File
@@ -93,6 +93,7 @@
- [State](#state) - [State](#state)
- [Routing](#routing) - [Routing](#routing)
- [Server Rendering](#server-rendering) - [Server Rendering](#server-rendering)
- [Components](#components)
- [Optimizations](#optimizations) - [Optimizations](#optimizations)
- [FAQ](#faq) - [FAQ](#faq)
- [API](#api) - [API](#api)
@@ -256,6 +257,13 @@ The current name of the route used in the router (e.g. `/foo/:bar`).
### `state.title` ### `state.title`
The current page title. Can be set using the `DOMTitleChange` event. The current page title. Can be set using the `DOMTitleChange` event.
### `state.components`
An object _recommended_ to use for local component state.
### `state.cache(Component, id, [...args])`
Generic class cache. Will lookup Component instance by id and create one if not
found. Usefull for working with statefull [components](#components).
## Routing ## Routing
Choo is an application level framework. This means that it takes care of Choo is an application level framework. This means that it takes care of
everything related to routing and pathnames for you. everything related to routing and pathnames for you.
@@ -340,6 +348,93 @@ the `window` object.
</html> </html>
``` ```
## Components
From time to time there will arise a need to have an element in an application
hold a self-contained state or to not rerender when the application does. This
is common when using 3rd party libraries to e.g. display an interactive map or a
graph and you rely on this 3rd party library to handle modifications to the DOM.
Components come baked in to Choo for these kinds of situations. See
[nanocomponent][nanocomponent] for documentation on the component class.
```javascript
// map.js
var html = require('choo/html')
var mapboxgl = require('mapbox-gl')
var Component = require('choo/component')
module.exports = class Button extends Component {
constructor (id, state, emit) {
super(id)
this.local = state.components[id] = {}
}
load (element) {
this.map = new mapboxgl.Map({
container: element,
center: this.local.center
})
}
update (center) {
if (center.join() !== this.local.center.join()) {
this.map.setCenter(center)
}
return false
}
createElement (center) {
this.local.center = center
return html`<div></div>`
}
}
```
```javascript
// index.js
var choo = require('choo')
var html = require('choo/html')
var Map = require('./map.js')
var app = choo()
app.route('/', mainView)
app.mount('body')
function mainView (state, emit) {
return html`
<body>
<button onclick=${onclick}>Where am i?</button>
${state.cache(Map, 'my-map').render(state.center)}
</body>
`
function onclick () {
emit('locate')
}
}
app.use(function (state, emitter) {
state.center = [18.0704503, 59.3244897]
emitter.on('locate', function () {
window.navigator.geolocation.getCurrentPosition(function (position) {
state.center = [position.coords.longitude, position.coords.latitude]
emitter.emit('render')
})
})
})
```
### Caching components
When working with stateful components, one will need to keep track of component
instances `state.cache` does just that. The component cache is a function
which takes a component class and a unique id (`string`) as it's first two
arguments. Any following arguments will be forwarded to the component contructor
together with `state` and `emit`.
The default class cache is an LRU cache (using [nanolru][nanolru]), meaning it
will only hold on to a fixed amount of class instances (`100` by default) before
starting to evict the least-recently-used instances. This behavior can be
overriden with [options](#app--chooopts).
## Optimizations ## Optimizations
Choo is reasonably fast out of the box. But sometimes you might hit a scenario Choo is reasonably fast out of the box. But sometimes you might hit a scenario
where a particular part of the UI slows down the application, and you want to where a particular part of the UI slows down the application, and you want to
@@ -434,6 +529,9 @@ Initialize a new `choo` instance. `opts` can also contain the following values:
history API. history API.
- __opts.href:__ default: `true`. Handle all relative `<a - __opts.href:__ default: `true`. Handle all relative `<a
href="<location>"></a>` clicks and call `emit('render')` href="<location>"></a>` clicks and call `emit('render')`
- __opts.cache:__ default: `undefined`. Override default class cache used by
`state.cache`. Can be a a `number` (maximum number of instances in cache,
default `100`) or an `object` with a [nanolru][nanolru]-compatible API.
### `app.use(callback(state, emitter, app))` ### `app.use(callback(state, emitter, app))`
Call a function and pass it a `state`, `emitter` and `app`. `emitter` is an instance Call a function and pass it a `state`, `emitter` and `app`. `emitter` is an instance
@@ -583,6 +681,8 @@ Become a backer, and buy us a coffee (or perhaps lunch?) every month or so.
## License ## License
[MIT](https://tldrlegal.com/license/mit-license) [MIT](https://tldrlegal.com/license/mit-license)
[nanocomponent]: https://github.com/choojs/nanocomponent
[nanolru]: https://github.com/s3ththompson/nanolru
[bankai]: https://github.com/choojs/bankai [bankai]: https://github.com/choojs/bankai
[bel]: https://github.com/shama/bel [bel]: https://github.com/shama/bel
[nanohtml]: https://github.com/choojs/nanohtml [nanohtml]: https://github.com/choojs/nanohtml