https://github.com/jiangfengming/vue-pilot
A Trie-based vue router with the ability of managing history.state.
https://github.com/jiangfengming/vue-pilot
Last synced: 7 months ago
JSON representation
A Trie-based vue router with the ability of managing history.state.
- Host: GitHub
- URL: https://github.com/jiangfengming/vue-pilot
- Owner: jiangfengming
- License: mit
- Created: 2017-04-01T08:29:57.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2020-08-27T06:29:15.000Z (over 5 years ago)
- Last Synced: 2025-04-21T17:56:51.229Z (8 months ago)
- Language: JavaScript
- Homepage:
- Size: 701 KB
- Stars: 11
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-vue - vue-pilot - A Trie-based vue router with the ability of managing history.state. (UI Utilities [🔝](#readme))
- awesome-vue - vue-pilot - A Trie-based vue router with the ability of managing history.state. (Components & Libraries / UI Utilities)
README
# vue-pilot
A Trie-based vue router with the ability of managing history.state.
## Install
```
npm install vue-pilot
```
## Features
* Small (8kb after gzipped).
* Ability of managing history.state.
* Decoupling UI layout from URL segments.
* Dispatching route without changing URL.
* Typed query and params.
## Table of Contents
- [vue-pilot](#vue-pilot)
- [Install](#install)
- [Features](#features)
- [Table of Contents](#table-of-contents)
- [Constructor](#constructor)
- [PathRouter](#pathrouter)
- [HashRouter](#hashrouter)
- [\](#routerview)
- [\](#routerlink)
- [Location object](#location-object)
- [path](#path)
- [external](#external)
- [query](#query)
- [hash](#hash)
- [fullPath](#fullpath)
- [url](#url)
- [state](#state)
- [hidden](#hidden)
- [appearPath](#appearpath)
- [Matched route object](#matched-route-object)
- [path](#path-1)
- [query](#query-1)
- [hash](#hash-1)
- [fullPath](#fullpath-1)
- [url](#url-1)
- [params](#params)
- [meta](#meta)
- [Routes definition](#routes-definition)
- [APIs](#apis)
- [router.current](#routercurrent)
- [router.start()](#routerstart)
- [router.normalize()](#routernormalize)
- [router.url()](#routerurl)
- [router.push()](#routerpush)
- [router.replace()](#routerreplace)
- [router.dispatch()](#routerdispatch)
- [router.setState()](#routersetstate)
- [router.go()](#routergo)
- [router.back()](#routerback)
- [router.forward()](#routerforward)
- [router.captureLinkClickEvent()](#routercapturelinkclickevent)
- [router.on()](#routeron)
- [router.off()](#routeroff)
- [Events](#events)
- [beforeChange](#beforechange)
- [Arguments](#arguments)
- [Returns](#returns)
- [beforeUpdate](#beforeupdate)
- [afterChange](#afterchange)
- [Dependencies](#dependencies)
- [License](#license)
## Constructor
### PathRouter
```js
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`. Let `` treats absolute URLs with `origin` as in-app links.
### HashRouter
```js
import Vue from 'vue'
import { HashRouter } from 'vue-pilot'
Vue.use(HashRouter)
const router = new HashRouter({
routes: [
// ...
]
})
```
`HashRouter` doesn't have `base` option.
## \
The `` is a functional component that renders the matched component.
It has a `name` property. The default value is `default`.
Example:
```html
```
## \
```html
List
Open new tab
Shoes
external link
```
The `` is a navigation component, it normally renders an `` element.
* `to`: `Location` object, or `path`/`fullPath` of the `Location` object, or an absolute URL.
* `action`: `String`. `push`, `replace`, or `dispatch`. Defaults to `push`.
* `tag`: `String`. The HTML tag name. Defaults to `a`.
`` will have `active` class if it equals to the current path.
## Location object
A location object is used for changing the current address.
It can be used in ``, `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()](#routernormalize).
And a location object can be converted to a URL string by [router.url()](#routerurl).
```js
{
path,
external,
query,
hash,
fullPath,
url,
state,
hidden,
appearPath
}
```
### path
`String`
Router internal path, which has stripped the protocol, host, and base path.
### external
`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.
### query
`Object` | `String` | `Array` | `URLSearchParams` | `StringCaster`
`query` accepts the same parameter types as [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams)
constructor. Or it can be a [StringCaster](https://github.com/jiangfengming/cast-string#stringcaster) object that wraps a `URLSearchParams` object.
### hash
`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.
### fullPath
`String`. Read-only.
path + query string + hash
### url
`String`. Read-only.
An external relative URL which can be used as `href` attribute of ``.
It is the same as `router.url(location)`.
* `PathRouter`: base + path + query string + hash
* `HashRouter`: # + path + query string + hash
### state
`Object`
The state object is a JavaScript object which is associated with the history entry.
See `state` parameter of [history.pushState()](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) for details.
### hidden
`Boolean`
Indicate whether it is a hidden history entry. see [router.push()](#routerpush) for detail.
### appearPath
`String`
If `hidden` is `true` and `appearPath` is set, the location bar will show this address instead.
## Matched route object
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.
```js
{
path,
query,
hash,
fullPath,
url,
state,
params,
meta
}
```
### path
`String`
Same as `location.path`.
### query
`StringCaster`
A [StringCaster](https://github.com/jiangfengming/cast-string#stringcaster) object that wraps a `URLSearchParams` object.
### hash
`String`
Same as `location.hash`.
### fullPath
`String`
Same as `location.fullPath`.
### url
`String`
Same as `location.url`.
### params
`StringCaster`
A [StringCaster](https://github.com/jiangfengming/cast-string#stringcaster) object that wraps a plain object.
The plain object is collected from the path segments.
See [Routes definition](#routes-definition) below for details.
### meta
`Object`
A object collected from the route definiton. See [Routes definition](#routes-definition) below for details.
## Routes definition
```js
const routes = [
{
name: 'aside', // will be mounted into
component: { /* component definition */ }
},
{
path: '/basic',
// Definition without `name`.
// The component will be mounted into
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 .
// 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
// `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
// `this` refers to the vue component instance.
beforeRouteLeave(to, from, action, router) {
},
// ...
}
},
// Use array to group definitions
// Router view definitions in array will override outer definitions which has the same name.
[
{
name: 'aside',
component: { /* ... */}
},
{
// In this layout, the default will mount a component that has nested s
component: {
props: ['activeTab'],
// Define two child s
template: `
`
},
// Define some meta
meta: { activeTab: 'main' },
// route.meta.activeTab is "foo" when path is "/foo"
props: route => ({ activeTab: route.meta.activeTab })
// Define child 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: '
404 Not Found
'
}
}
]
}
]
]
```
## APIs
Most of the APIs are proxied to [spa-history](https://github.com/jiangfengming/spa-history).
In the vue instance, you can get the router object from `this.$router`.
### router.current
The current [matched route object](#matched-route-object).
### router.start()
```js
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()
```js
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.
```js
// 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()](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams) for detail.
### router.url()
```js
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 ``.
```js
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()
```js
router.push(URL string | location)
```
Pushs the location onto the history stack. `beforeChange` event will be fired.
```js
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.
```js
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`
```js
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()
```js
router.replace(URL string | location)
```
Replaces the current history entry with the location specified.
### router.dispatch()
```js
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()
```js
router.setState(state)
```
Sets state of the current route. the state will be merged into `router.current.state`
### router.go()
```js
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()
```js
router.back(options)
```
Alias of `router.go(-1, options)`
### router.forward()
```js
router.forward(options)
```
Alias of `router.go(1, options)`
### router.captureLinkClickEvent()
```js
router.captureLinkClickEvent(event)
```
Prevents the navigation when clicking the `` element in the container and `href` is an in-app address,
`router.push()` will be called instead.
```html
```
### router.on()
```js
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()
```js
router.off(event, callback, { once = true })
```
Removes the specified event callback.
## Events
### beforeChange
```js
router.on('beforeChange', function(to, from, action, router) {
// ...
})
```
The `beforeChange` hook will be called before confirming the navigation.
`this` refers to the router instance.
#### Arguments
* 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
#### Returns
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'.
### beforeUpdate
```js
router.on('beforeUpdate', function(to, from, action, router) {
// ...
})
```
The `beforeUpdate` hook will be called after the history has been changed but before updating the ``s.
`this` refers to the router instance.
Returning `false` or a promise that resolves with `false` can prevent to update the ``s.
### afterChange
```js
router.on('afterChange', function(to, from, action, router) {
// ...
})
```
The `afterChange` hook will be called after ``s have been updated.
`this` refers to the router instance.
## Dependencies
- [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL)
- [Object.assign()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
- [Element.closest()](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest)
You can use [@babel/polyfill](https://babeljs.io/docs/en/babel-polyfill/) and
[dom4](https://github.com/WebReflection/dom4) to meet the requirements.
Or use the [polyfill.io](https://polyfill.io/) service:
```html
```
## License
[MIT](LICENSE)