Skip to content

Commit c541d7f

Browse files
committed
composable views
1 parent 03feaaa commit c541d7f

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

content/docs/views/index.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,69 @@ module.exports = function (state, emit) {
214214
showing the same title we already have, then we don't need to do anything.
215215
Conditional statements are less instructions on the CPU than function calls,
216216
so this provides us with a little speedup (and less noise).
217+
218+
## Composable Views
219+
As applications grow, you'll probably find that there will be plenty of views
220+
that share a lot of the same layout. If you find that you're repeating the same
221+
layout in a lot of code, it can be beneficial to make it reusable instead.
222+
223+
The most common way to create reusable templates, is to create a function that
224+
takes a view as an argument and returns a view. Inside the function the
225+
childView is called, and wrapped with some HTML. The end result is a nicely
226+
composed function that's also known as a "composable view", "higher order view",
227+
"template".
228+
229+
This might sound a little abstract. So let's create an example higher order
230+
view, which has a static header and footer, but takes the content as an
231+
argument.
232+
233+
_note: There's not an exact word for what we're doing here. Because it's a
234+
pattern, and not an API the exact word also doesn't matter too much. This is
235+
also not at all the only way to compose functions - so don't worry too much
236+
about getting the terminology right - we're also just making it up as we go._
237+
238+
```js
239+
var html = require('choo/html')
240+
var choo = require('choo')
241+
242+
var app = choo()
243+
app.route('/', template(main)) // 1.
244+
app.route('/bar', template(bar)) // 2.
245+
app.mount('body')
246+
247+
function template (childView) { // 3.
248+
return (state, emit) => { // 4.
249+
return html`
250+
<body>
251+
<header>This is the header</header>
252+
${childView(state, emit)}
253+
<footer>This is the footer</footer>
254+
</body>
255+
`
256+
}
257+
}
258+
259+
function main (state, emit) { // 5.
260+
return html`
261+
<h1>I'm the main view</h1>
262+
`
263+
}
264+
265+
function foo (state, emit) { // 6.
266+
return html`
267+
<h1>fooooooooooo view</h1>
268+
`
269+
}
270+
```
271+
272+
1. We create a route `'/'` which calls the `template` function, and passes it
273+
the `main` view function.
274+
2. We create a route `'/foo'` which calls the `template` function, and passes it
275+
the `foo` view function.
276+
3. This is where the bulk of the action happens. We create a function named
277+
`'template'` which takes a view as an argument (`childView`).
278+
4. The `'template'` function returns another function. This is the function
279+
we'll be passing to `app.route()`. It's a valid view. When the view is
280+
called, it calls the `childView`, and wraps it with DOM elements.
281+
5. We define a view named `'main'`.
282+
6. We define a view named `'foo'`.

0 commit comments

Comments
 (0)