Simple Svelte 3 hash based router with global routes.
Demo: https://tienpv222.github.io/svelte-hash-router
Demo REPL: https://svelte.dev/repl/47eaf2b35f4f4c98b533031f3b749c89?version=3.32.2
npm i -D svelte-hash-router
First, set the routes
schema before the root component.
// index.js
import { routes } from 'svelte-hash-router'
import App from './App.svelte'
import Home from './Home.svelte'
import About from './About.svelte'
routes.set({
'/home': Home,
'/about': About
})
export default new App({ target: document.body })
Then use Router
inside.
<!-- App.svelte -->
<script>
import Router from 'svelte-hash-router'
</script>
<Router/>
Or more simple:
// index.js
export default new Router({ target: document.body })
// schema
{
'/': {
$$component: MainLayout,
'home': Home,
'networking': {
$$component: NetworkingLayout,
'/github': Github,
'/facebook': Facebook
}
},
'*': NotFound
}
Then just simply use Router
for each level.
<!-- MainLayout.svelte -->
<div id='header'></div>
<Router/> <!-- match '/home' and '/networking' -->
<div id='footer'></div>
<!-- NetworkingLayout.svelte -->
<p>A social networking</p>
<Router/> <!-- match '/networking/github' and '/networking/facebook' -->
If $$component
in the parent is omitted:
// schema
{
'/': {
'home': Home,
'about': About
}
}
// will act the same as
{
'/home': Home,
'/about': About
}
Except that in the first schema, /
is an individual route, has its own data and can be looped for children routes when needed. See routes
.
Root paths must start with a /
or if using wildcard, *
.
import { routes, Router } from 'svelte-hash-router'
routes.set({
'/home': Home,
'*': NotFound
})
export default new Router({ target: document.body })
An object of options can be passed. All properties starting with $$
will be treated as options, the rest will be seen as nested routes. All options are saved as none-enumerable. $$component
is a reserved option.
{
'/home': HomeComponent,
'/about': {
// options
$$component: AboutComponent,
$$name: 'About me',
$$customOption: 'any',
// nested routes
'/biography': BiographyComponent,
'/hobbies': HobbiesComponent
}
}
Get params of current active route with the params store.
// schema
{
'/books/:id': BookComponent,
'/authors/:name/novels/:title': NovelComponent
}
// Svelte component
import { params } from 'svelte-hash-router'
// /books/123
$params.id === '123'
// /authors/John/novels/Dreams
$params.name === 'John'
$params.title === 'Dreams'
Same with query.
// Svelte component
import { query } from 'svelte-hash-router'
// /book?id=123&title=Dreams
$query.id === '123'
$query.title === 'Dreams'
The order of schema does matter. Whichever route matching first will be rendered. Wildcard *
matches anything, so it is usually put at the end. Wilcard is collected in params
as _
.
// schema
{ '/book/*': BookComponent }
// /book/123?title=Dreams
$params._ === '123' // not catch query
This library uses the nice package url-pattern, check it out for more syntaxes.
Redirect routes by using a string instead of a Svelte component, or if passing options object, use $$redirect
. The redirect path must be an asbolute path.
{
'/home': Home,
'/networking': {
'/github': GithubComponent,
// redirect using string syntax
'*': '/networking/github'
},
// redirect using options object
'*': {
$$redirect: '/home'
}
}
After the first schema setup, routes
becomes readonly. The following reserved properties are added for each route:
$$pathname
the exact path as in schema define$$href
full path including#
at the beginning$$stringify
a function to generate string from params. Check out url-pattern stringify$$pattern
url-pattern object
Since they are non-enumarable, you can easily loop for just nested routes when needed.
<!-- Navigator.svelte -->
<script>
import { routes, active } from 'svelte-hash-router'
$: links = Object.values($routes['/books']['/comedy'])
</script>
{#each links as e}
<a
class:active={e === $active}
href={e.$$href}
> {e.$$name}
</a>
{/each}
<style>
.active { color: blue; }
</style>
The store active
is the current active route. If you want to check if a parent route has an active child route, use the store matches
. It is an array including all the parents of the active route and itself.
<script>
import { matches } from 'svelte-hash-router'
</script>
<a class:active={$matches.includes(route)}></a>
A route containing params can be stringified.
<!-- schema: '/book/:id/:name' -->
<a href='{route.$$stringify({id: 123, name: `Dreams`})}'>
<!-- will give: '/book/123/Dreams' -->
Standard links to new pages should be preceded by a '#' symbol :
<a href='#/books'>