{"id":21983274,"url":"https://github.com/jiangfengming/vue-pilot","last_synced_at":"2025-04-30T06:21:46.177Z","repository":{"id":74863641,"uuid":"86897924","full_name":"jiangfengming/vue-pilot","owner":"jiangfengming","description":"A Trie-based vue router with the ability of managing history.state.","archived":false,"fork":false,"pushed_at":"2020-08-27T06:29:15.000Z","size":718,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-21T17:56:51.229Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jiangfengming.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-04-01T08:29:57.000Z","updated_at":"2020-11-16T12:15:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"faf0be97-653f-4a71-9b1f-ae229345fa24","html_url":"https://github.com/jiangfengming/vue-pilot","commit_stats":{"total_commits":187,"total_committers":4,"mean_commits":46.75,"dds":0.4331550802139037,"last_synced_commit":"e8deee45d69f3b548fb4988525b9f300b337d58a"},"previous_names":["fenivana/vue-router-x","jiangfengming/vue-stateful-router"],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiangfengming%2Fvue-pilot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiangfengming%2Fvue-pilot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiangfengming%2Fvue-pilot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiangfengming%2Fvue-pilot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jiangfengming","download_url":"https://codeload.github.com/jiangfengming/vue-pilot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251651879,"owners_count":21621836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T17:43:20.572Z","updated_at":"2025-04-30T06:21:46.155Z","avatar_url":"https://github.com/jiangfengming.png","language":"JavaScript","funding_links":[],"categories":["Components \u0026 Libraries","UI Utilities [🔝](#readme)"],"sub_categories":["UI Utilities"],"readme":"# vue-pilot\nA Trie-based vue router with the ability of managing history.state.\n\n## Install\n\n```\nnpm install vue-pilot\n```\n\n## Features\n* Small (8kb after gzipped).\n* Ability of managing history.state.\n* Decoupling UI layout from URL segments.\n* Dispatching route without changing URL.\n* Typed query and params.\n\n## Table of Contents\n- [vue-pilot](#vue-pilot)\n  - [Install](#install)\n  - [Features](#features)\n  - [Table of Contents](#table-of-contents)\n  - [Constructor](#constructor)\n    - [PathRouter](#pathrouter)\n    - [HashRouter](#hashrouter)\n  - [\\\u003cRouterView\u003e](#routerview)\n  - [\\\u003cRouterLink\u003e](#routerlink)\n  - [Location object](#location-object)\n    - [path](#path)\n    - [external](#external)\n    - [query](#query)\n    - [hash](#hash)\n    - [fullPath](#fullpath)\n    - [url](#url)\n    - [state](#state)\n    - [hidden](#hidden)\n    - [appearPath](#appearpath)\n  - [Matched route object](#matched-route-object)\n    - [path](#path-1)\n    - [query](#query-1)\n    - [hash](#hash-1)\n    - [fullPath](#fullpath-1)\n    - [url](#url-1)\n    - [params](#params)\n    - [meta](#meta)\n  - [Routes definition](#routes-definition)\n  - [APIs](#apis)\n    - [router.current](#routercurrent)\n    - [router.start()](#routerstart)\n    - [router.normalize()](#routernormalize)\n    - [router.url()](#routerurl)\n    - [router.push()](#routerpush)\n    - [router.replace()](#routerreplace)\n    - [router.dispatch()](#routerdispatch)\n    - [router.setState()](#routersetstate)\n    - [router.go()](#routergo)\n    - [router.back()](#routerback)\n    - [router.forward()](#routerforward)\n    - [router.captureLinkClickEvent()](#routercapturelinkclickevent)\n    - [router.on()](#routeron)\n    - [router.off()](#routeroff)\n  - [Events](#events)\n    - [beforeChange](#beforechange)\n      - [Arguments](#arguments)\n      - [Returns](#returns)\n    - [beforeUpdate](#beforeupdate)\n    - [afterChange](#afterchange)\n  - [Dependencies](#dependencies)\n  - [License](#license)\n\n## Constructor\n\n### PathRouter\n\n```js\nimport Vue from 'vue'\nimport { PathRouter } from 'vue-pilot'\n\nVue.use(PathRouter)\n\nconst router = new PathRouter({\n  routes: [\n    // see routes definition below\n  ],\n\n  base: '/app/',\n  origin: 'https://www.example.com/'\n})\n\nconst app = new Vue({\n  // inject the router instance\n  router,\n  \n  // ...\n})\n\nrouter.start()\n```\n\n`base`: `String`. defines the base path of the app. If you want the root path not end with slash,\nyou can set the base without ending slash, like '/app'. Defaults to `''`.\n\n`origin`: `String` | `Array\u003cString\u003e`. Let `\u003cRouterLink\u003e` treats absolute URLs with `origin` as in-app links.\n\n### HashRouter\n\n```js\nimport Vue from 'vue'\nimport { HashRouter } from 'vue-pilot'\n\nVue.use(HashRouter)\n\nconst router = new HashRouter({\n  routes: [\n    // ...\n  ]\n})\n```\n\n`HashRouter` doesn't have `base` option.\n\n## \\\u003cRouterView\u003e\n\nThe `\u003cRouterView\u003e` is a functional component that renders the matched component.\n\nIt has a `name` property.  The default value is `default`.\n\nExample:\n\n```html\n\u003cdiv id=\"app\"\u003e\n  \u003cRouterView name=\"aside\"\u003e\n  \u003cRouterView /\u003e\n\u003c/div\u003e\n```\n\n## \\\u003cRouterLink\u003e\n\n```html\n\u003cRouterLink to=\"/list?page=1\"\u003eList\u003c/RouterLink\u003e\n\u003cRouterLink to=\"/home\" target=\"_blank\"\u003eOpen new tab\u003c/RouterLink\u003e\n\n\u003cRouterLink\n  tag=\"div\"\n  action=\"replace\"\n  :to=\"{ path: '/category', query: { cat: 'shoes' }, state: { from: 'home' } }\"\n\u003e\n  Shoes\n\u003c/RouterLink\u003e\n\n\u003cRouterLink to=\"https://www.example.com\"\u003eexternal link\u003c/RouterLink\u003e\n```\n\nThe `\u003cRouterLink\u003e` is a navigation component, it normally renders an `\u003ca\u003e` element.\n\n* `to`: `Location` object, or `path`/`fullPath` of the `Location` object, or an absolute URL.\n* `action`: `String`. `push`, `replace`, or `dispatch`. Defaults to `push`.\n* `tag`: `String`. The HTML tag name. Defaults to `a`.\n\n`\u003cRouterLink\u003e` will have `active` class if it equals to the current path.\n\n## Location object\nA location object is used for changing the current address.\nIt can be used in `\u003cRouterLink :to=\"location\"\u003e`, `router.start(location)`, `router.push(location)`, `router.replace(location)`, `router.dispatch(location)`, etc.\n\nA string URL can be converted to a location object by [router.normalize()](#routernormalize).\nAnd a location object can be converted to a URL string by [router.url()](#routerurl).\n\n```js\n{\n  path,\n  external,\n  query,\n  hash,\n  fullPath,\n  url,\n  state,\n  hidden,\n  appearPath\n}\n```\n\n### path\n`String`\n\nRouter internal path, which has stripped the protocol, host, and base path.\n\n### external\n`Boolean`\n\nIf `path` is started with protocal, or `external` is `true`,\n`path` is treated as an external path, and will be converted to an internal path.\n\n### query\n`Object` | `String` | `Array` | `URLSearchParams` | `StringCaster\u003cURLSearchParams\u003e`\n\n`query` accepts the same parameter types as [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams)\nconstructor. Or it can be a [StringCaster](https://github.com/jiangfengming/cast-string#stringcaster) object that wraps a `URLSearchParams` object.\n\n### hash\n`String`\n\nA string containing a `#` followed by the fragment identifier of the URL.\nIf `HashRouter` is used, the fragment identifier is followed by the second `#` mark.\n\n### fullPath\n`String`. Read-only.\n\npath + query string + hash\n\n### url\n`String`. Read-only.\n\nAn external relative URL which can be used as `href` attribute of `\u003ca\u003e`.\nIt is the same as `router.url(location)`.\n\n* `PathRouter`: base + path + query string + hash\n* `HashRouter`: # + path + query string + hash\n\n### state\n`Object`\n\nThe state object is a JavaScript object which is associated with the history entry.\nSee `state` parameter of [history.pushState()](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) for details.\n\n### hidden\n`Boolean`\n\nIndicate whether it is a hidden history entry. see [router.push()](#routerpush) for detail.\n\n### appearPath\n`String`\n\nIf `hidden` is `true` and `appearPath` is set, the location bar will show this address instead.\n\n## Matched route object\nA matched route object contains the information of the matched route.\nIt contains some same properties as the `Location` object, and some extra properties.\nIt's provided by the hook functions as the `to` and `from` parameter.\n\n```js\n{\n  path,\n  query,\n  hash,\n  fullPath,\n  url,\n  state,\n  params,\n  meta\n}\n```\n\n### path\n`String`\n\nSame as `location.path`.\n\n### query\n`StringCaster`\n\nA [StringCaster](https://github.com/jiangfengming/cast-string#stringcaster) object that wraps a `URLSearchParams` object.\n\n### hash\n`String`\n\nSame as `location.hash`.\n\n### fullPath\n`String`\n\nSame as `location.fullPath`.\n\n### url\n`String`\n\nSame as `location.url`.\n\n### params\n`StringCaster`\n\nA [StringCaster](https://github.com/jiangfengming/cast-string#stringcaster) object that wraps a plain object.\nThe plain object is collected from the path segments.\nSee [Routes definition](#routes-definition) below for details.\n\n### meta\n`Object`\n\nA object collected from the route definiton. See [Routes definition](#routes-definition) below for details.\n\n## Routes definition\n\n```js\nconst routes = [\n  {\n    name: 'aside', // will be mounted into \u003cRouterView name=\"aside\"\u003e\n    component: { /* component definition */ }\n  },\n\n  {\n    path: '/basic',\n\n    // Definition without `name`.\n    // The component will be mounted into \u003cRouterView name=\"default\"\u003e\n    component: { /* component definition */ }\n  },\n\n  // Return promise to define async components\n  { path: '/async', component: () =\u003e import('./Component.vue') },\n\n  {\n    path: '/prop',\n\n    // Pass some props to the component\n    props: { foo: 'hello' },\n\n    component: {\n      props: ['foo'],\n      // ...\n    }\n  },\n\n  {\n    // Use `:paramName` to define params\n    // More pattern syntax, see https://github.com/jiangfengming/url-router\n    path: '/article/:id',\n\n    // props can be a factory function, it receives the current route object as the first argument.\n    props: route =\u003e ({\n      articleId: route.params.int('id'),\n      foo: route.query.string('foo'),\n      bar: route.state.bar\n    }),\n\n    component: {\n      props: ['articleId', 'foo', 'bar'],\n      // ...\n    },\n\n    // Setting key attribute of the \u003cRouterView\u003e.\n    // It will re-create the component instead of reusing it when key changes.\n    // So you needn't to watch the prop changes.\n    // See https://vuejs.org/v2/api/#key\n    // If key is a function, the returned value will be the key\n    key: route =\u003e route.params.int('id')\n  },\n\n  {\n    // param with regex\n    path: '/date/:year(\\\\d+)-:month(\\\\d+)',\n    component: VFoo,\n    props: route =\u003e ({ foo: route.params.int('year'), bar: route.params.int('month') })\n  },\n\n  // Define hooks\n  {\n    path: '/login',\n\n    // beforeEnter hook will be called before confirming the navigation.\n    // See global `beforeChange` event for details.\n    // Function | Array\u003cFunction\u003e\n    // `this` refers to the router instance.\n    beforeEnter(to, from, action, router) {\n\n    },\n\n    component: {\n      // in-component beforeRouteLeave hook.\n      // Will be called before route leave.\n      // See global `beforeChange` event for details.\n      // Function | Array\u003cFunction\u003e\n      // `this` refers to the vue component instance.\n      beforeRouteLeave(to, from, action, router) {\n\n      },\n\n      // ...\n    }\n  },\n\n\n  // Use array to group \u003cRouterView\u003e definitions\n  // Router view definitions in array will override outer definitions which has the same name.\n  [\n    {\n      name: 'aside',\n      component: { /* ... */}\n    },\n\n    {\n      // In this layout, the default \u003cRouterView\u003e will mount a component that has nested \u003cRouterView\u003es\n      component: {\n        props: ['activeTab'],\n\n        // Define two child \u003cRouterView\u003es\n        template: `\n          \u003cRouterView /\u003e\n          \u003cRouterView name=\"footer\" /\u003e\n        `\n      },\n\n      // Define some meta\n      meta: { activeTab: 'main' },\n\n      // route.meta.activeTab is \"foo\" when path is \"/foo\"\n      props: route =\u003e ({ activeTab: route.meta.activeTab })\n\n      // Define child \u003cRouterView\u003es\n      children: [\n        {\n          name: 'footer',\n          component: { /* ... */ }\n        },\n\n        {\n          path: '/foo',\n          component: { /* ... */ },\n\n          // Parent route meta and child route meta will be merged together.\n          // If child route meta has same keys as parent, it will override parent ones.\n          meta: { activeTab: 'foo' }\n        },\n\n        [\n          // Override footer\n          {\n            name: 'footer',\n            component: { /* ... */ }\n          },\n\n          {\n            path: '/bar',\n            component: { /* ... */},\n\n            // meta can be a factory function\n            meta: route =\u003e ({ activeTab: route.query.string('active') })\n          }\n        ],\n\n        // Define a catch-all route\n        {\n          path: '(.*)',\n          component: {\n            template: '\u003ch1\u003e404 Not Found\u003c/h1\u003e'\n          }\n        }\n      ]\n    }\n  ]\n]\n```\n\n## APIs\nMost of the APIs are proxied to [spa-history](https://github.com/jiangfengming/spa-history).\n\nIn the vue instance, you can get the router object from `this.$router`.\n\n### router.current\nThe current [matched route object](#matched-route-object).\n\n### router.start()\n\n```js\nrouter.start(URL string | location)\n```\n\nStarts the router.\n\nIn browser, if URL/location is not given, the default value is the current address.\n\n### router.normalize()\n\n```js\nrouter.normalize(URL string | location)\n```\n\nconverts the URL string or unnormalized location object to a normalized object.\n\nif 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.\n\n```js\n// PathRouter with base '/foo/bar/'\nrouter.normalize('http://www.example.com/foo/bar/home?a=1#b')\n/*\n  {\n    path: '/home',\n    query: new StringCaster(new URLSearchParams('a=1')),\n    hash: '#b',\n    fullPath: '/home?a=1#b',\n    state: {}\n  }\n*/\n\n// same result as above\nrouter.normalize({\n  path: '/foo/bar/home?a=1#b',\n  external: true\n})\n\n// same result as above\nrouter.normalize('/home?a=1#b')\n\n// same result as above\nrouter.normalize({\n  path: '/home',\n  query: {\n    a: 1\n  },\n  hash: '#b'\n})\n\n// HashRouter\n// same result as above\nrouter.normalize('http://www.example.com/app/#/home?a=1#b')\n```\n\nThe `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.\n\n### router.url()\n\n```js\nrouter.url(URL string | location)\n```\n\nConverts an internal URL string or location object to an external relative URL which can be set as `href` attribute of `\u003ca\u003e`.\n\n```js\nrouter.url({\n  path: '/home',\n  query: {\n    a: 1\n  },\n  hash: '#b'\n})\n\n// or\nrouter.url('/home?a=1#b')\n\n/*\n  result:\n  HashRouter: #/home?a=1#b\n  PathRouter(with base: '/foo/bar/'): /foo/bar/home?a=1#b\n*/\n```\n\n### router.push()\n\n```js\nrouter.push(URL string | location)\n```\n\nPushs the location onto the history stack. `beforeChange` event will be fired.\n\n```js\nrouter.push('/home?a=1#b')\n\nrouter.push({\n  path: '/home',\n  query: {\n    a: 1\n  },\n  hash: '#b'\n})\n\n// PathRouter, complete URL\nrouter.push('http://www.example.com/foo/bar/home?a=1#b')\n\n// HashRouter, complete URL\nrouter.push('http://www.example.com/#/home?a=1#b')\n```\n\nYou can push a location with state.\n\n```js\nrouter.push({\n  path: '/home',\n  state: {\n    foo: 1,\n    bar: 2\n  }\n})\n```\n\nAnd 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`\n\n```js\nrouter.push({\n  path: '/login',\n  state: {\n    foo: 1\n  },\n\n  // '/login' won't show in the location bar\n  hidden: true,\n\n  // optional. if set, the location bar will show this address instead\n  appearPath: '/buy'\n})\n```\n\n### router.replace()\n\n```js\nrouter.replace(URL string | location)\n```\n\nReplaces the current history entry with the location specified.\n\n### router.dispatch()\n\n```js\nrouter.dispatch(URL string | location)\n```\n\nDispatchs the route without changing the history. That is, the location of browser's address bar won't be changed.\n\n### router.setState()\n\n```js\nrouter.setState(state)\n```\n\nSets state of the current route. the state will be merged into `router.current.state`\n\n### router.go()\n\n```js\nrouter.go(position, { silent = false, state = null } = {})\n```\n\nCounterpart of `window.history.go()`. Returns a promise which will be resolved when `popstate` event fired.\n\n`silent`: if true, `beforeChange` event won't be fired.\n\n`state`: if set, the state object will be merged into the state object of the destination location.\n\n### router.back()\n\n```js\nrouter.back(options)\n```\n\nAlias of `router.go(-1, options)`\n\n### router.forward()\n\n```js\nrouter.forward(options)\n```\n\nAlias of `router.go(1, options)`\n\n### router.captureLinkClickEvent()\n\n```js\nrouter.captureLinkClickEvent(event)\n```\n\nPrevents the navigation when clicking the `\u003ca\u003e` element in the container and `href` is an in-app address,\n`router.push()` will be called instead.\n\n```html\n\u003cdiv @click=\"$router.captureLinkClickEvent($event)\"\u003e\n  \u003ca href=\"/foo\"\u003efoo\u003c/a\u003e\n\u003c/div\u003e\n```\n\n### router.on()\n\n```js\nrouter.on(event, callback, { once = false, beginning = false })\n```\n\nAdds a callback function that will be called when the specified event fires.\n\nIf `once` is `true`, the callback function will be removed after \n\nIf `beginning` is `true`, the callback function will be inserted at the beginning of the callback array,\nso it will be called first.\n\n### router.off()\n\n```js\nrouter.off(event, callback, { once = true })\n```\n\nRemoves the specified event callback.\n\n## Events\n\n### beforeChange\n\n```js\nrouter.on('beforeChange', function(to, from, action, router) {\n  // ...\n})\n```\n\nThe `beforeChange` hook will be called before confirming the navigation.\n`this` refers to the router instance.\n\n#### Arguments\n* to: Route object. The route will be changed to.\n* from: Route object. The current route.\n* action:\n    - push: router.push() is called.\n    - replace: router.replace() is called.\n    - init: \"to\" is the initial page, at this stage, \"from.path\" is null.\n    - pop: user clicked the back or foraward button , or router.go(), router.back(), router.forward() is called, or hash changed.\n    - dispatch: router.dispatch() is called.\n* router: the router instance\n\n#### Returns\n\nThe hook can return one of the following values, or a promise that resolves with one of the following values,\nto control the navigation:\n\n* true | undefined: The navigation is confirmed.\n* false: Prevent the navigation.\n* null: Do nothing.\n* location: Redirect to this location.\n            You can override the history manipulate action by providing location.action property, values are: 'push', 'replace', 'dispatch'.\n\n### beforeUpdate\n\n```js\nrouter.on('beforeUpdate', function(to, from, action, router) {\n  // ...\n})\n```\n\nThe `beforeUpdate` hook will be called after the history has been changed but before updating the `\u003cRouterView\u003e`s.\n`this` refers to the router instance.\n\nReturning `false` or a promise that resolves with `false` can prevent to update the `\u003cRouterView\u003e`s.\n\n### afterChange\n\n```js\nrouter.on('afterChange', function(to, from, action, router) {\n  // ...\n})\n```\n\nThe `afterChange` hook will be called after `\u003cRouterView\u003e`s have been updated.\n`this` refers to the router instance.\n\n## Dependencies\n- [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL)\n- [Object.assign()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\n- [Element.closest()](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest)\n\nYou can use [@babel/polyfill](https://babeljs.io/docs/en/babel-polyfill/) and\n[dom4](https://github.com/WebReflection/dom4) to meet the requirements.\n\nOr use the [polyfill.io](https://polyfill.io/) service:\n```html\n\u003cscript src=\"https://polyfill.io/v3/polyfill.min.js\"\u003e\u003c/script\u003e\n```\n\n## License\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiangfengming%2Fvue-pilot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjiangfengming%2Fvue-pilot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiangfengming%2Fvue-pilot/lists"}