remove default route, parse qs (#521)
This commit is contained in:
@@ -23,6 +23,11 @@ events: `'navigate'` will trigger whenever a route changes, `'replaceState'`
|
||||
can be called to redirect routes, and `popState` which is emitted when the back
|
||||
button in the browser is pressed.
|
||||
|
||||
To top things off, we've reintroduced querystring parsing. An object containing
|
||||
the current represenation of the search query (e.g. `?foo=bar`) can be found
|
||||
under `state.query`. We used to do something similar in choo v4 and below, and
|
||||
we're happy to reintroduce it in this release!
|
||||
|
||||
And that's about it - we've upgraded a whole slew of deps, and removed a few we
|
||||
didn't quite use. Overall we're quite proud of the new codebase, and filled
|
||||
with joy we didn't have to make any changes to the API - additions only.
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
- [Philosophy](#philosophy)
|
||||
- [Events](#events)
|
||||
- [State](#state)
|
||||
- [Routing](#routing)
|
||||
- [Server Rendering](#server-rendering)
|
||||
- [Optimizations](#optimizations)
|
||||
- [FAQ](#faq)
|
||||
@@ -224,9 +225,50 @@ The current params taken from the route. E.g. `/foo/:bar` becomes available as
|
||||
`state.params.bar` If a wildcard route is used (`/foo/*`) it's available as
|
||||
`state.params.wildcard`.
|
||||
|
||||
### `state.query`
|
||||
An object containing the current queryString. `/foo?bin=baz` becomes `{ bin:
|
||||
'baz' }`.
|
||||
|
||||
### `state.route`
|
||||
The current name of the route used in the router (e.g. `/foo/:bar`).
|
||||
|
||||
## Routing
|
||||
Choo is an application level framework. This means that it takes care of
|
||||
everything related to routing and pathnames for you.
|
||||
|
||||
### Params
|
||||
Params can be registered by prepending the routename with `:routename`, e.g.
|
||||
`/foo/:bar/:baz`. The value of the param will be saved on `state.params` (e.g.
|
||||
`state.params.bar`). Wildcard routes can be registered with `*`, e.g. `/foo/*`.
|
||||
The value of the wildcard will be saved under `state.params.wildcard`.
|
||||
|
||||
### Default routes
|
||||
Sometimes a route doesn't match, and you want to display a page to handle it.
|
||||
You can do this by declaring `app.route('*', handler)` to handle all routes
|
||||
that didn't match anything else.
|
||||
|
||||
### Querystrings
|
||||
Querystrings (e.g. `?foo=bar`) are ignored when matching routes. An object
|
||||
containing the key-value mappings exists as `state.query`.
|
||||
|
||||
### Hash routing
|
||||
Using hashes to delimit routes is supported out of the box (e.g. `/foo#bar`).
|
||||
When a hash is found we also check if there's an available anchor on the same
|
||||
page, and will scroll the screen to the position. Using both hashes in URLs and
|
||||
anchor links on the page is generally not recommended.
|
||||
|
||||
### Following links
|
||||
By default all clicks on `<a>` tags are handled by the router. If the `href=""`
|
||||
attrbibute points to the same `origin` (e.g. the same page), and it doesn't
|
||||
have a `rel="nooper"` attribute or similar, we handle the route. This can be
|
||||
disabled application-wide by passing `{ href: false }` to the application
|
||||
constructor. Uses [nanohref](https://github.com/yoshuawuyts/nanohref) under the
|
||||
hood.
|
||||
|
||||
### Navigating programmatically
|
||||
To can navigate routes you can emit `'pushState'`, `'popState'` or
|
||||
`'replaceState'`. See [#events](#events) for more details about these events.
|
||||
|
||||
## Server Rendering
|
||||
Choo was built with Node in mind. To render on the server call `.toString()` on
|
||||
your application.
|
||||
@@ -351,31 +393,12 @@ messages by calling `emitter.on()` and emit messages by calling
|
||||
|
||||
See [#events](#events) for an overview of all events.
|
||||
|
||||
### `app.route(routeName, handler)`
|
||||
Register a route on the router. Uses [nanorouter][nanorouter] under the hood.
|
||||
Params can be registered by prepending the routename with `:routename`, e.g.
|
||||
`/foo/:bar/:baz`. The value of the param will be saved on `state.params` (e.g.
|
||||
`state.params.bar`). Wildcard routes can be registered with `*`, e.g. `/foo/*`.
|
||||
The value of the wildcard will be saved under `state.params.wildcard`.
|
||||
### `app.route(routeName, handler(state, emit))`
|
||||
Register a route on the router. The handler function is passed `app.state`
|
||||
and `app.emitter.emit` as arguments. Uses [nanorouter][nanorouter] under the
|
||||
hood.
|
||||
|
||||
Using hashes to delimit routes is supported out of the box (e.g. `/foo#bar`).
|
||||
When a hash is found we also check if there's an available anchor on the same
|
||||
page, and will scroll the screen to the position. Using both hashes in URLs and
|
||||
anchor links on the page is generally not recommended.
|
||||
|
||||
New routes can be triggered through `emitter.emit('pushState', <routename>)`.
|
||||
By default we also catch and match all `<a href="">` clicks against the router.
|
||||
This can be disabled by setting `opts.href` to `false` in the constructor.
|
||||
Routing via `pushState` will not work until the `DOMContentLoaded` event has
|
||||
been fired.
|
||||
|
||||
If you need choo to ignore a particular route, you can add `data-no-routing`
|
||||
attribute with `<a href="" data-no-routing>`. This is especially useful for
|
||||
directing outside the choo app.
|
||||
|
||||
Querystrings (`?foo=bar`) are ignored when matching routes. They should be
|
||||
extracted from the `window.location` object on render events, from either a
|
||||
custom event listener or the matched views.
|
||||
See [#routing](#routing) for an overview of how to use routing efficiently.
|
||||
|
||||
### `app.mount(selector)`
|
||||
Start the application and mount it on the given `querySelector`. Uses
|
||||
|
||||
+3
-4
@@ -16,10 +16,8 @@ if (module.parent) {
|
||||
var app = choo()
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
var persist = require('choo-persist')
|
||||
var logger = require('choo-log')
|
||||
app.use(persist())
|
||||
app.use(logger())
|
||||
app.use(require('choo-persist')())
|
||||
app.use(require('choo-log')())
|
||||
}
|
||||
app.use(expose())
|
||||
app.use(todoStore)
|
||||
@@ -27,6 +25,7 @@ if (module.parent) {
|
||||
app.route('/', mainView)
|
||||
app.route('#active', mainView)
|
||||
app.route('#completed', mainView)
|
||||
app.route('*', mainView)
|
||||
app.mount('body')
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"bel": "^4.5.1",
|
||||
"choo-expose": "^1.0.0",
|
||||
"choo-log": "^6.0.0",
|
||||
"choo-log": "^7.0.0-0",
|
||||
"choo-persist": "^3.0.0",
|
||||
"microbounce": "^1.0.0",
|
||||
"microframe": "^1.0.0",
|
||||
|
||||
@@ -3,6 +3,7 @@ var documentReady = require('document-ready')
|
||||
var nanotiming = require('nanotiming')
|
||||
var nanorouter = require('nanorouter')
|
||||
var nanomorph = require('nanomorph')
|
||||
var nanoquery = require('nanoquery')
|
||||
var nanohref = require('nanohref')
|
||||
var nanoraf = require('nanoraf')
|
||||
var nanobus = require('nanobus')
|
||||
@@ -18,11 +19,6 @@ function Choo (opts) {
|
||||
|
||||
assert.equal(typeof opts, 'object', 'choo: opts should be type object')
|
||||
|
||||
var routerOpts = {
|
||||
default: opts.defaultRoute || '/404',
|
||||
curry: true
|
||||
}
|
||||
|
||||
// define events used by choo
|
||||
this._events = {
|
||||
DOMCONTENTLOADED: 'DOMContentLoaded',
|
||||
@@ -39,7 +35,7 @@ function Choo (opts) {
|
||||
this._tree = null
|
||||
|
||||
// properties that are part of the API
|
||||
this.router = nanorouter(routerOpts)
|
||||
this.router = nanorouter({ curry: true })
|
||||
this.emitter = nanobus('choo.emit')
|
||||
this.state = { events: this._events }
|
||||
}
|
||||
@@ -78,6 +74,7 @@ Choo.prototype.start = function () {
|
||||
if (this._historyEnabled) {
|
||||
this.emitter.prependListener(this._events.NAVIGATE, function () {
|
||||
self.emitter.emit(self._events.RENDER)
|
||||
self.state.query = nanoquery(window.location.search)
|
||||
setTimeout(scrollToAnchor.bind(null, window.location.hash), 0)
|
||||
})
|
||||
|
||||
@@ -113,6 +110,7 @@ Choo.prototype.start = function () {
|
||||
|
||||
var location = this._createLocation()
|
||||
this._tree = this.router(location)
|
||||
this.state.query = nanoquery(window.location.search)
|
||||
assert.ok(this._tree, 'choo.start: no valid DOM node returned for location ' + location)
|
||||
|
||||
this.emitter.prependListener(self._events.RENDER, nanoraf(function () {
|
||||
@@ -169,6 +167,7 @@ Choo.prototype.toString = function (location, state) {
|
||||
assert.equal(typeof location, 'string', 'choo.toString: location should be type string')
|
||||
assert.equal(typeof this.state, 'object', 'choo.toString: state should be type object')
|
||||
|
||||
this.state.query = nanoquery(location)
|
||||
var html = this.router(location)
|
||||
assert.ok(html, 'choo.toString: no valid value returned for the route ' + location)
|
||||
return html.toString()
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"nanobus": "^4.2.0",
|
||||
"nanohref": "^2.0.0",
|
||||
"nanomorph": "^5.1.2",
|
||||
"nanoquery": "^1.1.0",
|
||||
"nanoraf": "^3.0.0",
|
||||
"nanorouter": "^2.0.0",
|
||||
"nanotiming": "^6.0.0",
|
||||
|
||||
Reference in New Issue
Block a user