A Trie-based vue router with the ability of managing history.state.
npm install vue-pilot
- Small (8kb after gzipped).
- Ability of managing history.state.
- Decoupling UI layout from URL segments.
- Dispatching route without changing URL.
- Typed query and params.
- vue-pilot
import Vue from 'vue'
import { PathRouter } from 'vue-pilot'
Vue.use(PathRouter)
const router = new PathRouter({
routes: [
// see routes definition below
],
base: '/app/',
origin: 'https://www.example.com/'
})
const app = new Vue({
// inject the router instance
router,
// ...
})
router.start()
base
: String
. defines the base path of the app. If you want the root path not end with slash,
you can set the base without ending slash, like '/app'. Defaults to ''
.
origin
: String
| Array<String>
. Let <RouterLink>
treats absolute URLs with origin
as in-app links.
import Vue from 'vue'
import { HashRouter } from 'vue-pilot'
Vue.use(HashRouter)
const router = new HashRouter({
routes: [
// ...
]
})
HashRouter
doesn't have base
option.
The <RouterView>
is a functional component that renders the matched component.
It has a name
property. The default value is default
.
Example:
<div id="app">
<RouterView name="aside">
<RouterView />
</div>
<RouterLink to="/list?page=1">List</RouterLink>
<RouterLink to="/home" target="_blank">Open new tab</RouterLink>
<RouterLink
tag="div"
action="replace"
:to="{ path: '/category', query: { cat: 'shoes' }, state: { from: 'home' } }"
>
Shoes
</RouterLink>
<RouterLink to="https://www.example.com">external link</RouterLink>
The <RouterLink>
is a navigation component, it normally renders an <a>
element.
to
:Location
object, orpath
/fullPath
of theLocation
object, or an absolute URL.action
:String
.push
,replace
, ordispatch
. Defaults topush
.tag
:String
. The HTML tag name. Defaults toa
.
<RouterLink>
will have active
class if it equals to the current path.
A location object is used for changing the current address.
It can be used in <RouterLink :to="location">
, router.start(location)
, router.push(location)
, router.replace(location)
, router.dispatch(location)
, etc.
A string URL can be converted to a location object by router.normalize(). And a location object can be converted to a URL string by router.url().
{
path,
external,
query,
hash,
fullPath,
url,
state,
hidden,
appearPath
}
String
Router internal path, which has stripped the protocol, host, and base path.
Boolean
If path
is started with protocal, or external
is true
,
path
is treated as an external path, and will be converted to an internal path.
Object
| String
| Array
| URLSearchParams
| StringCaster<URLSearchParams>
query
accepts the same parameter types as URLSearchParams
constructor. Or it can be a StringCaster object that wraps a URLSearchParams
object.
String
A string containing a #
followed by the fragment identifier of the URL.
If HashRouter
is used, the fragment identifier is followed by the second #
mark.
String
. Read-only.
path + query string + hash
String
. Read-only.
An external relative URL which can be used as href
attribute of <a>
.
It is the same as router.url(location)
.
PathRouter
: base + path + query string + hashHashRouter
: # + path + query string + hash
Object
The state object is a JavaScript object which is associated with the history entry.
See state
parameter of history.pushState() for details.
hidden
Boolean
Indicate whether it is a hidden history entry. see router.push() for detail.
String
If hidden
is true
and appearPath
is set, the location bar will show this address instead.
A matched route object contains the information of the matched route.
It contains some same properties as the Location
object, and some extra properties.
It's provided by the hook functions as the to
and from
parameter.
{
path,
query,
hash,
fullPath,
url,
state,
params,
meta
}
String
Same as location.path
.
StringCaster
A StringCaster object that wraps a URLSearchParams
object.
String
Same as location.hash
.
String
Same as location.fullPath
.
String
Same as location.url
.
StringCaster
A StringCaster object that wraps a plain object. The plain object is collected from the path segments. See Routes definition below for details.
Object
A object collected from the route definiton. See Routes definition below for details.
const routes = [
{
name: 'aside', // will be mounted into <RouterView name="aside">
component: { /* component definition */ }
},
{
path: '/basic',
// Definition without `name`.
// The component will be mounted into <RouterView name="default">
component: { /* component definition */ }
},
// Return promise to define async components
{ path: '/async', component: () => import('./Component.vue') },
{
path: '/prop',
// Pass some props to the component
props: { foo: 'hello' },
component: {
props: ['foo'],
// ...
}
},
{
// Use `:paramName` to define params
// More pattern syntax, see https://github.com/jiangfengming/url-router
path: '/article/:id',
// props can be a factory function, it receives the current route object as the first argument.
props: route => ({
articleId: route.params.int('id'),
foo: route.query.string('foo'),
bar: route.state.bar
}),
component: {
props: ['articleId', 'foo', 'bar'],
// ...
},
// Setting key attribute of the <RouterView>.
// It will re-create the component instead of reusing it when key changes.
// So you needn't to watch the prop changes.
// See https://vuejs.org/v2/api/#key
// If key is a function, the returned value will be the key
key: route => route.params.int('id')
},
{
// param with regex
path: '/date/:year(\\d+)-:month(\\d+)',
component: VFoo,
props: route => ({ foo: route.params.int('year'), bar: route.params.int('month') })
},
// Define hooks
{
path: '/login',
// beforeEnter hook will be called before confirming the navigation.
// See global `beforeChange` event for details.
// Function | Array<Function>
// `this` refers to the router instance.
beforeEnter(to, from, action, router) {
},
component: {
// in-component beforeRouteLeave hook.
// Will be called before route leave.
// See global `beforeChange` event for details.
// Function | Array<Function>
// `this` refers to the vue component instance.
beforeRouteLeave(to, from, action, router) {
},
// ...
}
},
// Use array to group <RouterView> definitions
// Router view definitions in array will override outer definitions which has the same name.
[
{
name: 'aside',
component: { /* ... */}
},
{
// In this layout, the default <RouterView> will mount a component that has nested <RouterView>s
component: {
props: ['activeTab'],
// Define two child <RouterView>s
template: `
<RouterView />
<RouterView name="footer" />
`
},
// Define some meta
meta: { activeTab: 'main' },
// route.meta.activeTab is "foo" when path is "/foo"
props: route => ({ activeTab: route.meta.activeTab })
// Define child <RouterView>s
children: [
{
name: 'footer',
component: { /* ... */ }
},
{
path: '/foo',
component: { /* ... */ },
// Parent route meta and child route meta will be merged together.
// If child route meta has same keys as parent, it will override parent ones.
meta: { activeTab: 'foo' }
},
[
// Override footer
{
name: 'footer',
component: { /* ... */ }
},
{
path: '/bar',
component: { /* ... */},
// meta can be a factory function
meta: route => ({ activeTab: route.query.string('active') })
}
],
// Define a catch-all route
{
path: '(.*)',
component: {
template: '<h1>404 Not Found</h1>'
}
}
]
}
]
]
Most of the APIs are proxied to spa-history.
In the vue instance, you can get the router object from this.$router
.
The current matched route object.
router.start(URL string | location)
Starts the router.
In browser, if URL/location is not given, the default value is the current address.
router.normalize(URL string | location)
converts the URL string or unnormalized location object to a normalized object.
if URL/location.path is started with protocal, or location.external
is true
, location.path
is treated as an external path, and will be converted to an internal path.
// PathRouter with base '/foo/bar/'
router.normalize('http://www.example.com/foo/bar/home?a=1#b')
/*
{
path: '/home',
query: new StringCaster(new URLSearchParams('a=1')),
hash: '#b',
fullPath: '/home?a=1#b',
state: {}
}
*/
// same result as above
router.normalize({
path: '/foo/bar/home?a=1#b',
external: true
})
// same result as above
router.normalize('/home?a=1#b')
// same result as above
router.normalize({
path: '/home',
query: {
a: 1
},
hash: '#b'
})
// HashRouter
// same result as above
router.normalize('http://www.example.com/app/#/home?a=1#b')
The query
property can be of type Object
, String
or Array
. see URLSearchParams() for detail.
router.url(URL string | location)
Converts an internal URL string or location object to an external relative URL which can be set as href
attribute of <a>
.
router.url({
path: '/home',
query: {
a: 1
},
hash: '#b'
})
// or
router.url('/home?a=1#b')
/*
result:
HashRouter: #/home?a=1#b
PathRouter(with base: '/foo/bar/'): /foo/bar/home?a=1#b
*/
router.push(URL string | location)
Pushs the location onto the history stack. beforeChange
event will be fired.
router.push('/home?a=1#b')
router.push({
path: '/home',
query: {
a: 1
},
hash: '#b'
})
// PathRouter, complete URL
router.push('http://www.example.com/foo/bar/home?a=1#b')
// HashRouter, complete URL
router.push('http://www.example.com/#/home?a=1#b')
You can push a location with state.
router.push({
path: '/home',
state: {
foo: 1,
bar: 2
}
})
And you can push a hidden location, which will not change the value of browser's address bar. the hidden location is stored in window.history.state
router.push({
path: '/login',
state: {
foo: 1
},
// '/login' won't show in the location bar
hidden: true,
// optional. if set, the location bar will show this address instead
appearPath: '/buy'
})
router.replace(URL string | location)
Replaces the current history entry with the location specified.
router.dispatch(URL string | location)
Dispatchs the route without changing the history. That is, the location of browser's address bar won't be changed.
router.setState(state)
Sets state of the current route. the state will be merged into router.current.state
router.go(position, { silent = false, state = null } = {})
Counterpart of window.history.go()
. Returns a promise which will be resolved when popstate
event fired.
silent
: if true, beforeChange
event won't be fired.
state
: if set, the state object will be merged into the state object of the destination location.
router.back(options)
Alias of router.go(-1, options)
router.forward(options)
Alias of router.go(1, options)
router.captureLinkClickEvent(event)
Prevents the navigation when clicking the <a>
element in the container and href
is an in-app address,
router.push()
will be called instead.
<div @click="$router.captureLinkClickEvent($event)">
<a href="/foo">foo</a>
</div>
router.on(event, callback, { once = false, beginning = false })
Adds a callback function that will be called when the specified event fires.
If once
is true
, the callback function will be removed after
If beginning
is true
, the callback function will be inserted at the beginning of the callback array,
so it will be called first.
router.off(event, callback, { once = true })
Removes the specified event callback.
router.on('beforeChange', function(to, from, action, router) {
// ...
})
The beforeChange
hook will be called before confirming the navigation.
this
refers to the router instance.
- to: Route object. The route will be changed to.
- from: Route object. The current route.
- action:
- push: router.push() is called.
- replace: router.replace() is called.
- init: "to" is the initial page, at this stage, "from.path" is null.
- pop: user clicked the back or foraward button , or router.go(), router.back(), router.forward() is called, or hash changed.
- dispatch: router.dispatch() is called.
- router: the router instance
The hook can return one of the following values, or a promise that resolves with one of the following values, to control the navigation:
- true | undefined: The navigation is confirmed.
- false: Prevent the navigation.
- null: Do nothing.
- location: Redirect to this location. You can override the history manipulate action by providing location.action property, values are: 'push', 'replace', 'dispatch'.
router.on('beforeUpdate', function(to, from, action, router) {
// ...
})
The beforeUpdate
hook will be called after the history has been changed but before updating the <RouterView>
s.
this
refers to the router instance.
Returning false
or a promise that resolves with false
can prevent to update the <RouterView>
s.
router.on('afterChange', function(to, from, action, router) {
// ...
})
The afterChange
hook will be called after <RouterView>
s have been updated.
this
refers to the router instance.
You can use @babel/polyfill and dom4 to meet the requirements.
Or use the polyfill.io service:
<script src="https://polyfill.io/v3/polyfill.min.js"></script>