├── .circleci └── config.yml ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── babel.config.js ├── build └── build.js ├── dist ├── vue-router-lite.es6.js ├── vue-router-lite.es6.min.js ├── vue-router-lite.js ├── vue-router-lite.module.js ├── vue-router-lite.umd.js └── vue-router-lite.umd.min.js ├── docs ├── .vuepress │ ├── components │ │ └── Bit.vue │ ├── config.js │ ├── public │ │ ├── _redirects │ │ └── bit-wide.png │ ├── style.styl │ └── theme │ │ ├── components │ │ ├── BuySellAds.vue │ │ └── CarbonAds.vue │ │ ├── index.js │ │ └── layouts │ │ └── Layout.vue ├── README.md ├── advanced │ └── data-fetching.md ├── api │ └── README.md ├── guide │ ├── README.md │ ├── all.md │ ├── control-history.md │ ├── navigation.md │ ├── preventing-transitions.md │ ├── redirects.md │ ├── route-info.md │ ├── route-matching.md │ └── routers.md ├── installation.md ├── package-lock.json └── package.json ├── examples ├── active-links │ ├── app.js │ └── index.html ├── ambiguous-matches │ ├── app.js │ └── index.html ├── auth-flow │ ├── app.js │ ├── auth.js │ ├── components │ │ ├── About.vue │ │ ├── App.vue │ │ ├── CheckLogin.vue │ │ ├── Dashboard.vue │ │ └── Login.vue │ └── index.html ├── basic │ ├── app.js │ └── index.html ├── control-history │ ├── app.js │ └── index.html ├── custom-link │ ├── app.js │ └── index.html ├── data-fetching │ ├── Post.vue │ ├── api.js │ ├── app.js │ └── index.html ├── global.css ├── hash-router │ ├── app.js │ └── index.html ├── index.html ├── keep-alive │ ├── app.js │ └── index.html ├── memory-router │ ├── app.js │ └── index.html ├── modal-gallery │ ├── app.js │ └── index.html ├── modal-gallery2 │ ├── app.js │ └── index.html ├── no-match │ ├── app.js │ └── index.html ├── preventing-transitions │ ├── app.js │ └── index.html ├── recursive-paths │ ├── app.js │ └── index.html ├── route-config │ ├── app.js │ └── index.html ├── server.js ├── sidebar │ ├── app.js │ └── index.html ├── static-router │ ├── app.js │ └── index.html ├── transitions │ ├── app.js │ └── index.html ├── url-parameters │ ├── app.js │ └── index.html └── webpack.config.js ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── component │ ├── BrowserRouter.vue │ ├── HashRouter.vue │ ├── MemoryRouter.vue │ ├── Prompt.vue │ ├── Redirect.vue │ ├── Route.vue │ ├── RouteContext.vue │ ├── RouteSwitch.vue │ ├── Router.vue │ ├── RouterLink.vue │ ├── StaticRouter.vue │ └── Tag.vue ├── index.js └── util │ ├── createBrowserHistory.js │ ├── createHashHistory.js │ ├── createMemoryHistory.js │ ├── createStaticHistory.js │ ├── generatePath.js │ ├── matchPath.js │ ├── symbol.js │ └── utils.js └── test └── specs ├── apps ├── BrowserRouter.vue ├── HashRouter.vue ├── MemoryRouter.vue ├── RouterApp.vue ├── StaticRouter.vue └── components │ ├── About.vue │ ├── Home.vue │ ├── Topic.vue │ └── Topics.vue └── router.test.js /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | defaults: &defaults 4 | working_directory: ~/project/vue-router-lite 5 | docker: 6 | - image: circleci/node:lts-browsers 7 | 8 | jobs: 9 | install: 10 | <<: *defaults 11 | steps: 12 | - checkout 13 | - restore_cache: 14 | keys: 15 | - v1-vue-router-lite-{{ .Branch }}-{{ checksum "package-lock.json" }} 16 | - v1-vue-router-lite-{{ .Branch }}- 17 | - v1-vue-router-lite 18 | - restore_cache: 19 | keys: 20 | - v1-vue-router-lite-docs-{{ .Branch }}-{{ checksum "docs/package-lock.json" }} 21 | - v1-vue-router-lite-docs-{{ .Branch }}- 22 | - v1-vue-router-lite-docs 23 | - run: npm install && cd docs && npm install 24 | - save_cache: 25 | key: v1-vue-router-lite-{{ .Branch }}-{{ checksum "package-lock.json" }} 26 | paths: 27 | - node_modules/ 28 | - save_cache: 29 | key: v1-vue-router-lite-docs-{{ .Branch }}-{{ checksum "docs/package-lock.json" }} 30 | paths: 31 | - docs/node_modules/ 32 | - persist_to_workspace: 33 | root: ~/project 34 | paths: 35 | - vue-router-lite 36 | 37 | docs-examples: 38 | <<: *defaults 39 | steps: 40 | - add_ssh_keys: 41 | fingerprints: 42 | - "e6:03:a3:2c:0c:7f:18:c8:9a:ac:57:92:c8:f4:8a:a6" 43 | - attach_workspace: 44 | at: ~/project 45 | # init gh-pages 46 | - run: cd ../ && mkdir gh-pages 47 | # docs 48 | - run: VUEPRESS_BASE=/vue-router-lite/docs/ npm run docs:build && cp -r docs/.vuepress/dist ../gh-pages/docs 49 | # examples 50 | - run: PUBLIC_PATH=/vue-router-lite/examples/ npm run examples:build && cp -r examples/__build__ ../gh-pages/examples 51 | # push 52 | - run: echo -e "Host *\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config 53 | - run: cd ../gh-pages && git init && git config --global user.email "season.chen.i@foxmail.com" && git config --global user.name "Season Chen" && git add -A && git commit -m 'deploy [ci skip]' && git push -f git@github.com:ccqgithub/vue-router-lite.git master:gh-pages 54 | 55 | # lint-flow-types: 56 | # <<: *defaults 57 | # steps: 58 | # - attach_workspace: 59 | # at: ~/project 60 | # - run: yarn run lint 61 | # - run: yarn run flow 62 | # - run: yarn run test:types 63 | 64 | test-unit: 65 | <<: *defaults 66 | steps: 67 | - attach_workspace: 68 | at: ~/project 69 | - run: npm run test 70 | # add codecov once it is actually ran 71 | # - run: 72 | # name: report coverage stats for non-PRs 73 | # command: | 74 | # if [[ -z $CI_PULL_REQUEST ]]; then 75 | # ./node_modules/.bin/codecov 76 | # fi 77 | 78 | # test-e2e: 79 | # <<: *defaults 80 | # steps: 81 | # - attach_workspace: 82 | # at: ~/project 83 | # - run: yarn run test:e2e 84 | 85 | # test-e2e-bs-ie9: 86 | # <<: *defaults 87 | # steps: 88 | # - attach_workspace: 89 | # at: ~/project 90 | # - run: yarn run test:e2e:ie9 91 | 92 | workflows: 93 | version: 2 94 | all: 95 | jobs: 96 | - install: 97 | filters: 98 | branches: 99 | only: master 100 | - docs-examples: 101 | requires: 102 | - install 103 | filters: 104 | branches: 105 | only: master 106 | - test-unit: 107 | requires: 108 | - install 109 | filters: 110 | branches: 111 | only: master 112 | # - lint-flow-types: 113 | # requires: 114 | # - install 115 | # - test-e2e: 116 | # requires: 117 | # - install 118 | # - test-e2e-bs-ie9: 119 | # requires: 120 | # - install 121 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | test 3 | examples -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserOptions: { 3 | // move it into parserOptions, for eslint-plugin-vue 4 | // https://github.com/vuejs/eslint-plugin-vue#couple-faq 5 | parser: 'babel-eslint', 6 | ecmaVersion: 2018, 7 | sourceType: 'module' 8 | }, 9 | plugins: [ 10 | // https://github.com/babel/eslint-plugin-babel 11 | 'babel', 12 | // https://github.com/prettier/eslint-plugin-prettier 13 | 'prettier' 14 | ], 15 | extends: [ 16 | // https://github.com/vuejs/eslint-plugin-vue#bulb-rules 17 | 'plugin:vue/strongly-recommended', 18 | 19 | // https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb 20 | 'airbnb-base', 21 | 22 | // https://github.com/prettier/eslint-plugin-prettier 23 | 'prettier', 24 | 'prettier/react', 25 | 'prettier/standard', 26 | 'prettier/vue' 27 | ], 28 | env: { 29 | browser: true, 30 | es6: true 31 | }, 32 | rules: { 33 | eqeqeq: 'warn', 34 | 'prettier/prettier': 'warn', 35 | 'no-unused-vars': ['warn', { args: 'none' }], 36 | 'no-console': 'off', 37 | 'no-script-url': 'warn', 38 | 'no-shadow': 'warn', 39 | 'no-plusplus': 'off', 40 | 'no-param-reassign': 'off', 41 | 'no-underscore-dangle': 'off', 42 | 'prefer-const': 'off', 43 | 'prefer-destructuring': 'off', 44 | 'import/no-extraneous-dependencies': 'off', 45 | 'import/prefer-default-export': 'off', 46 | 'import/no-dynamic-require': 'off', 47 | 'global-require': 'off', 48 | 'consistent-return': 'off', 49 | 'max-classes-per-file': 'off', 50 | 'arrow-body-style': 'off', 51 | 'class-methods-use-this': 'off', 52 | 'prefer-arrow-callback': 'off', 53 | 'vue/html-quotes': 'error', 54 | 'vue/this-in-template': 'error', 55 | 'vue/max-attributes-per-line': [ 56 | 'warn', 57 | { 58 | singleline: 20, 59 | multiline: { 60 | max: 1, 61 | allowFirstLine: false 62 | } 63 | } 64 | ] 65 | }, 66 | overrides: [ 67 | { 68 | files: ['build/**/*'], 69 | parserOptions: { 70 | // move it into parserOptions, for eslint-plugin-vue 71 | // https://github.com/vuejs/eslint-plugin-vue#couple-faq 72 | parser: 'espree', 73 | ecmaVersion: 2018, 74 | sourceType: 'module', 75 | ecmaFeatures: { 76 | jsx: true 77 | } 78 | }, 79 | env: { 80 | browser: false, 81 | node: true 82 | } 83 | } 84 | ] 85 | }; 86 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.pid 3 | *.seed 4 | 5 | .DS_Store 6 | 7 | .idea 8 | .tags* 9 | 10 | /coverage/ 11 | node_modules 12 | /docs/.vuepress/dist 13 | /examples/__build__ 14 | 15 | npm-debug.log* 16 | # yarn.lock 17 | # package-lock.json 18 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /** 2 | !dist/** 3 | !src/** 4 | !LICENSE 5 | !README.md 6 | !package.json -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 80, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: true, 7 | quoteProps: 'preserve', 8 | jsxSingleQuote: false, 9 | trailingComma: 'none', 10 | bracketSpacing: true, 11 | jsxBracketSameLine: false, 12 | arrowParens: 'always', 13 | requirePragma: false, 14 | insertPragma: false, 15 | proseWrap: 'preserve', 16 | htmlWhitespaceSensitivity: 'css', 17 | vueIndentScriptAndStyle: false, 18 | endOfLine: 'auto', 19 | overrides: [ 20 | { 21 | files: '*.css', 22 | options: { 23 | singleQuote: false 24 | } 25 | }, 26 | { 27 | files: '*.less', 28 | options: { 29 | singleQuote: false 30 | } 31 | }, 32 | { 33 | files: '*.scss', 34 | options: { 35 | singleQuote: false 36 | } 37 | }, 38 | { 39 | files: '*.md', 40 | options: {} 41 | } 42 | ] 43 | }; 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019-present Season Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-route-lite 2 | 3 | > A component-based, declarative router for `vue@2.6+`. Inspired by `react-router@4.x`. 4 | 5 | ## Introduction 6 | 7 | `vue-router-lite` is a component-based router for [Vue.js](http://vuejs.org/). Read [Documents](http://ccqgithub.github.io/vue-router-lite/docs/) for more details. 8 | 9 | Features include: 10 | 11 | - Component-Based: just use some HOC(Higher-Order Components) to control your routes. 12 | - Nested routes or mapping routes. 13 | - Modal support. 14 | - Fine-grained navigation control. 15 | - View transition effects powered by Vue.js' transition system. 16 | - Keep Alive. 17 | - Links with automatic active CSS classes. 18 | - HTML5 history mode or hash mode or memory mode. 19 | - Some other features that [vue-router](https://github.com/vuejs/vue-router) and [react-router4](https://reacttraining.com/react-router/) can do. 20 | 21 | ## Doccuments And Examples 22 | 23 | - [Examples](http://ccqgithub.github.io/vue-router-lite/examples/). 24 | - [Examples Code](https://github.com/ccqgithub/vue-router-lite/tree/master/examples). 25 | - [Documentations](http://ccqgithub.github.io/vue-router-lite/docs/). 26 | - [Documentations Code](https://github.com/ccqgithub/vue-router-lite/tree/master/docs). 27 | 28 | ## Development Setup 29 | 30 | ```sh 31 | # install deps 32 | npm install 33 | 34 | # build dist files 35 | npm run build 36 | 37 | # unit test 38 | npm run test 39 | 40 | # serve examples at localhost:8080 41 | npm run examples 42 | 43 | # serve docs at localhost:8080 44 | cd docs 45 | npm install 46 | npm run docs 47 | ``` 48 | 49 | ## Inspired By 50 | 51 | - [react-router4](https://reacttraining.com/react-router/) 52 | - [vue-router](https://github.com/vuejs/vue-router) 53 | - [vue-component-router](https://github.com/blocka/vue-component-router) 54 | 55 | ## Dependences 56 | 57 | - [vue@2.6+](https://vuejs.org/): peer dependence, need vue2.6+'s new unified slot syntax. 58 | - [history@4.x](https://github.com/ReactTraining/history) 59 | - [path-to-regexp@3.x](https://github.com/pillarjs/path-to-regexp) 60 | 61 | ## License 62 | 63 | [MIT](http://opensource.org/licenses/MIT) 64 | 65 | Copyright (c) 2019-present [Season Chen](https://github.com/ccqgithub) 66 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | babelrc: false, 3 | exclude: ['node_modules/**/*'], 4 | plugins: [ 5 | '@babel/plugin-proposal-object-rest-spread' 6 | ], 7 | presets: [ 8 | ['@babel/env', { modules: false }] 9 | ], 10 | env: { 11 | test: { 12 | presets: [ 13 | ['@babel/env', { targets: { node: 'current' } }] 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | const { rollup } = require('rollup'); 2 | const cjsPlugin = require('@rollup/plugin-commonjs'); 3 | const resolvePlugin = require('@rollup/plugin-node-resolve'); 4 | const replacePlugin = require('@rollup/plugin-replace'); 5 | const babelPlugin = require('rollup-plugin-babel'); 6 | const vuePlugin = require('rollup-plugin-vue'); 7 | const filesizePlugin = require('rollup-plugin-filesize'); 8 | const terserPlugin = require('rollup-plugin-terser').terser; 9 | 10 | const fs = require('fs-extra'); 11 | const path = require('path'); 12 | 13 | const pkg = require('../package.json'); 14 | 15 | const version = process.env.VERSION || pkg.version; 16 | const banner = `/*! 17 | * vue-router-lite v${version} 18 | * (c) 2019-present Season Chen 19 | * @license MIT 20 | */`; 21 | const resolve = (_path) => path.resolve(__dirname, '../', _path); 22 | let external = []; 23 | external = external.concat(Object.keys(pkg.dependencies || {})); 24 | external = external.concat(Object.keys(pkg.peerDependencies || {})); 25 | 26 | // make sure we're in the right folder 27 | process.chdir(path.resolve(__dirname, '../')); 28 | 29 | fs.removeSync('../dist'); 30 | 31 | async function generateBundledModule({ 32 | inputFile, 33 | outputFile, 34 | format, 35 | min, 36 | env, 37 | es5, 38 | external = [] 39 | }) { 40 | console.log(`Generating ${outputFile} bundle.`); 41 | 42 | // basic 43 | let plugins = [ 44 | vuePlugin({ 45 | css: false 46 | }), 47 | cjsPlugin(), 48 | resolvePlugin(), 49 | replacePlugin({ 50 | __VERSION__: version 51 | }) 52 | ]; 53 | 54 | // process.env.NODE_ENV 55 | if (env) { 56 | plugins.push( 57 | replacePlugin({ 58 | 'process.env.NODE_ENV': JSON.stringify(env) 59 | }) 60 | ); 61 | } 62 | 63 | // babel compield to es5 64 | if (es5) { 65 | plugins.push(babelPlugin({})); 66 | } 67 | 68 | // min 69 | if (min) { 70 | plugins.push(terserPlugin()); 71 | } 72 | 73 | // file size 74 | plugins.push(filesizePlugin()); 75 | 76 | // bundle 77 | const bundle = await rollup({ 78 | input: inputFile, 79 | plugins, 80 | external 81 | }); 82 | 83 | await bundle.write({ 84 | file: outputFile, 85 | format, 86 | banner, 87 | exports: 'named', 88 | name: format === 'umd' ? 'VueRouterLite' : undefined 89 | }); 90 | 91 | console.log(`Generation of ${outputFile} bundle finished.`); 92 | } 93 | 94 | // outputs 95 | const outputs = [ 96 | // umd for no need compile 97 | { 98 | file: resolve('dist/vue-router-lite.umd.js'), 99 | format: 'umd', 100 | env: 'development', 101 | es5: true 102 | }, 103 | { 104 | file: resolve('dist/vue-router-lite.umd.min.js'), 105 | format: 'umd', 106 | env: 'production', 107 | es5: true, 108 | min: true 109 | }, 110 | 111 | // cjs, need to compile with `process.env.NODE_ENV` and `dependencies` 112 | { 113 | file: resolve('dist/vue-router-lite.js'), 114 | format: 'cjs', 115 | es5: true, 116 | external 117 | }, 118 | 119 | // es module, need to compile with `process.env.NODE_ENV` and `dependencies` 120 | { 121 | file: resolve('dist/vue-router-lite.module.js'), 122 | format: 'es', 123 | es5: true, 124 | external 125 | }, 126 | 127 | // es6, no need compile, work in envirements that es6 native support 128 | { 129 | file: resolve('dist/vue-router-lite.es6.js'), 130 | format: 'es', 131 | env: 'development' 132 | }, 133 | { 134 | file: resolve('dist/vue-router-lite.es6.min.js'), 135 | format: 'es', 136 | env: 'production', 137 | min: true 138 | } 139 | ]; 140 | 141 | async function build() { 142 | const inputFile = path.join(__dirname, '../src/index.js'); 143 | await Promise.all( 144 | outputs.map((item) => { 145 | return generateBundledModule({ 146 | inputFile, 147 | outputFile: item.file, 148 | format: item.format, 149 | es5: item.es5, 150 | env: item.env, 151 | min: item.min, 152 | external: item.external 153 | }); 154 | }) 155 | ); 156 | } 157 | 158 | build().catch((e) => { 159 | console.error(e); 160 | if (e.frame) { 161 | console.error(e.frame); 162 | } 163 | process.exit(1); 164 | }); 165 | -------------------------------------------------------------------------------- /docs/.vuepress/components/Bit.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | base: process.env.VUEPRESS_BASE || '/', 3 | locales: { 4 | '/': { 5 | lang: 'en-US', 6 | title: 'Vue Router Lite', 7 | description: 'A cpmponent-based router for Vue.js.' 8 | }, 9 | // '/zh/': { 10 | // lang: 'zh-CN', 11 | // title: 'Vue Router', 12 | // description: '基于组件的 Vue.js 路由管理器。' 13 | // }, 14 | }, 15 | serviceWorker: true, 16 | // theme: '@vuepress/default', 17 | themeConfig: { 18 | repo: 'ccqgithub/vue-router-lite', 19 | docsDir: 'docs', 20 | locales: { 21 | '/': { 22 | label: 'English', 23 | selectText: 'Languages', 24 | editLinkText: 'Edit this page on GitHub', 25 | nav: [ 26 | { 27 | text: 'Guide', 28 | link: '/guide/' 29 | }, 30 | { 31 | text: 'API Reference', 32 | link: '/api/' 33 | }, 34 | { 35 | text: 'Release Notes', 36 | link: 'https://github.com/ccqgithub/vue-router-lite/releases' 37 | } 38 | ], 39 | sidebar: [ 40 | '/installation.md', 41 | '/', 42 | { 43 | title: 'Essentials', 44 | collapsable: false, 45 | children: [ 46 | '/guide/', 47 | '/guide/routers.md', 48 | '/guide/route-matching.md', 49 | '/guide/route-info.md', 50 | '/guide/control-history.md', 51 | '/guide/navigation.md', 52 | '/guide/redirects.md', 53 | '/guide/preventing-transitions.md' 54 | ] 55 | }, 56 | { 57 | title: 'Advanced', 58 | collapsable: false, 59 | children: [ 60 | '/advanced/data-fetching.md' 61 | ] 62 | } 63 | ] 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /docs/.vuepress/public/_redirects: -------------------------------------------------------------------------------- 1 | # redirect old urls to root 2 | 3 | /en/essentials/getting-started.html /guide/ 4 | /en/essentials/* /guide/essentials/:splat 5 | /en/advanced/* /guide/advanced/:splat 6 | /en/api/* /api/ 7 | /en/* /:splat 8 | 9 | /zh-cn/essentials/getting-started.html /zh/guide/ 10 | /zh-cn/essentials/* /zh/guide/essentials/:splat 11 | /zh-cn/advanced/* /zh/guide/advanced/:splat 12 | /zh-cn/api/* /zh/api/ 13 | /zh-cn/* /zh/:splat 14 | 15 | /ru/essentials/getting-started.html /ru/guide/ 16 | /ru/essentials/* /ru/guide/essentials/:splat 17 | /ru/advanced/* /ru/guide/advanced/:splat 18 | /ru/api/* /ru/api/ 19 | /ru/* /ru/:splat 20 | 21 | /ja/essentials/getting-started.html /ja/guide/ 22 | /ja/essentials/* /ja/guide/essentials/:splat 23 | /ja/advanced/* /ja/guide/advanced/:splat 24 | /ja/api/* /ja/api/ 25 | /ja/* /ja/:splat 26 | 27 | /kr/essentials/getting-started.html /kr/guide/ 28 | /kr/essentials/* /kr/guide/essentials/:splat 29 | /kr/advanced/* /kr/guide/advanced/:splat 30 | /kr/api/* /kr/api/ 31 | /kr/* /kr/:splat 32 | -------------------------------------------------------------------------------- /docs/.vuepress/public/bit-wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccqgithub/vue-router-lite/263243e95c7db0374ce3d7c3353c22022b64a428/docs/.vuepress/public/bit-wide.png -------------------------------------------------------------------------------- /docs/.vuepress/style.styl: -------------------------------------------------------------------------------- 1 | .bit-sponsor 2 | font-weight 600 3 | background-color #f3f6f8 4 | padding 0.6em 1.2em 5 | border-radius 8px 6 | display inline-block 7 | margin 1em 0 !important 8 | a 9 | color #999 10 | img 11 | height 40px 12 | margin-left 15px 13 | img, span 14 | vertical-align middle 15 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/BuySellAds.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/CarbonAds.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extend: '@vuepress/theme-default' 3 | } -------------------------------------------------------------------------------- /docs/.vuepress/theme/layouts/Layout.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | :::tip VERSION NOTE 4 | Requires `vue@2.6+`. 5 | ::: 6 | 7 | `vue-router-lite` is a component-based router for [Vue.js](http://vuejs.org/). 8 | 9 | Features include: 10 | 11 | - Component-Based: just use some HOC(Higher-Order Components) to control your routes. 12 | - Nested routes or mapping routes 13 | - Modal support 14 | - Fine-grained navigation control 15 | - View transition effects powered by Vue.js' transition system 16 | - Keep Alive 17 | - Links with automatic active CSS classes 18 | - HTML5 history mode or hash mode or memory mode 19 | - Some other features that [vue-router](https://github.com/vuejs/vue-router) and [react-router4](https://reacttraining.com/react-router/) can do. 20 | 21 | [Get started](./guide/) or play with the [Examples](https://github.com/ccqgithub/vue-router-lite/tree/master/examples) (see [`README.md`](https://github.com/ccqgithub/vue-router-lite) to run them). 22 | 23 | [Live Examples](https://github.com/ccqgithub/vue-router-lite/tree/master/examples). 24 | -------------------------------------------------------------------------------- /docs/advanced/data-fetching.md: -------------------------------------------------------------------------------- 1 | # Data Fetching 2 | 3 | todo -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # API Reference 6 | 7 | All `component`s or `method`s can import as below: 8 | 9 | ```js 10 | import { 11 | // components 12 | BrowserRouter, 13 | HashRouter, 14 | MemoryRouter, 15 | StaticRouter, 16 | Router, 17 | RouterLink, 18 | Prompt, 19 | Redirect, 20 | Route, 21 | RouteContext, 22 | RouteSwitch, 23 | 24 | // methods 25 | generatePath, 26 | matchPath, 27 | createBrowserHistory, 28 | createHashHistory, 29 | createMemoryHistory, 30 | createStaticHistory 31 | } from 'vue-router-lite'; 32 | 33 | const App = { 34 | components: { 35 | BrowserRouter, 36 | Route, 37 | RouterLink, 38 | RouteSwitch 39 | // 40 | Home, 41 | About, 42 | Topics 43 | }, 44 | template: ` 45 | 46 |
47 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
71 |
72 | ` 73 | } 74 | ``` 75 | 76 | ## `` 77 | 78 | The common low-level interface for all router components. Typically apps will use one of the high-level routers instead: 79 | 80 | - `` 81 | - `` 82 | - `` 83 | - `` 84 | 85 | All the router components must have a single slot child, that will receive these props: 86 | 87 | - `history` 88 | - `location` 89 | - `match` 90 | 91 | ```js 92 | const history = createBrowserHistory({ 93 | basename: '/', 94 | //... 95 | }); 96 | 97 | new Vue({ 98 | template: ` 99 | 103 | 104 | 105 | ` 106 | }); 107 | ``` 108 | 109 | Props: 110 | 111 | ### history 112 | 113 | - Type: `History` 114 | - Required 115 | 116 | A [history](https://github.com/ReactTraining/history) object to use for navigation. 117 | 118 | 119 | ## `` 120 | 121 | A `` that uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL. 122 | 123 | ```html 124 | 131 | 132 | 133 | ``` 134 | 135 | Props: read `createBrowserHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 136 | 137 | ### basename 138 | 139 | - Type: `String` 140 | - Defaults: `''` 141 | 142 | The base URL for all locations. If your app is served from a sub-directory on your server, you’ll want to set this to the sub-directory. A properly formatted basename should have a leading slash, but no trailing slash (like `/basename`). 143 | 144 | ### getUserConfirmation 145 | 146 | - Type: `Function` 147 | 148 | A function to use to confirm navigation. Defaults to using `window.confirm` like below. 149 | 150 | ```js 151 | // this is the default behavior 152 | function getConfirmation(message, callback) { 153 | const allowTransition = window.confirm(message); 154 | callback(allowTransition); 155 | } 156 | ``` 157 | 158 | ### forceRefresh 159 | 160 | - Type: `Boolean` 161 | - Defaults: `false` 162 | 163 | If true the router will use full page refreshes on page navigation. You probably only want this in browsers that don’t support the `HTML5 history API`. 164 | 165 | ### keyLength 166 | 167 | - Type: `Number` 168 | - Defaults: `6` 169 | 170 | The length of location.key. Read more details on [location.key](https://github.com/ReactTraining/history#listening). 171 | 172 | 173 | ## `` 174 | 175 | A `` that uses the hash portion of the URL (i.e. window.location.hash) to keep your UI in sync with the URL. 176 | 177 | **IMPORTANT NOTE**: Hash history does not support `location.key` or `location.state`. 178 | 179 | > Read `createHashHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 180 | 181 | ```html 182 | 188 | 189 | 190 | ``` 191 | 192 | Props: 193 | 194 | ### basename 195 | 196 | - Type: `String` 197 | - Defaults: `''` 198 | 199 | The base URL for all locations. A properly formatted basename should have a leading slash, but no trailing slash (like '/basename'). 200 | 201 | ### hashType 202 | 203 | - Type: `String` 204 | - Defaults: `'slash'` 205 | 206 | The type of encoding to use for window.location.hash. Available values are: 207 | 208 | - "slash" - Creates hashes like `#/` and `#/sunshine/lollipops` 209 | - "noslash" - Creates hashes like `#` and `#sunshine/lollipops` 210 | - "hashbang" - Creates “ajax crawlable” (deprecated by Google) hashes like `#!/` and `#!/sunshine/lollipops` 211 | 212 | ### getUserConfirmation 213 | 214 | - Type: `Function` 215 | 216 | A function to use to confirm navigation. Defaults to using `window.confirm` like below. 217 | 218 | ```js 219 | // this is the default behavior 220 | function getConfirmation(message, callback) { 221 | const allowTransition = window.confirm(message); 222 | callback(allowTransition); 223 | } 224 | ``` 225 | 226 | 227 | ## `` 228 | 229 | A `` that keeps the history of your “URL” in memory (does not read or write to the address bar). Useful in tests and non-browser environments. 230 | 231 | > Read `createMemoryHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 232 | 233 | ```html 234 | 241 | 242 | 243 | ``` 244 | 245 | Props: 246 | 247 | ### initialEntries 248 | 249 | - Type: `[String | Location]` 250 | - Defaults: `['/']` 251 | 252 | An array of locations in the history stack. These may be full-blown `location` objects with { pathname, search, hash, state } or simple string URLs. 253 | 254 | ### initialIndex 255 | 256 | - Type: `Number` 257 | - Defaults: `0` 258 | 259 | The initial location’s index in the array of initialEntries. 260 | 261 | ### keyLength 262 | 263 | - Type: `Number` 264 | - Defaults: `6` 265 | 266 | The length of location.key. 267 | 268 | ### getUserConfirmation 269 | 270 | - Type: `Function` 271 | - Defaults: `null` 272 | 273 | A function to use to confirm navigation. You must use this option when using `` directly with a ``. 274 | 275 | 276 | ## `` 277 | 278 | A `` that never changes location. 279 | 280 | ```html 281 | 287 | 288 | 289 | ``` 290 | 291 | Props: 292 | 293 | ### basename 294 | 295 | - Type: `String` 296 | - Defaults: `''` 297 | 298 | The base URL for all locations. A properly formatted basename should have a leading slash, but no trailing slash (like `/basename`). 299 | 300 | ### context 301 | 302 | - Type: `Object` 303 | - Defaults: `{}` 304 | 305 | A plain JavaScript object. During the render, components can add properties to the object to store information about the render. 306 | 307 | ### location 308 | 309 | - Type: `[String | Location]` 310 | - Defaults: `'/'` 311 | 312 | The URL the server received, probably `req.url` on a node server. Or a `location` object shaped like `{ pathname, search, hash, state }`. 313 | 314 | 315 | ## `` 316 | 317 | The `` component is perhaps the most important component in `vue-router-lite` to understand and learn to use well. Its most basic responsibility is to render some UI when a location matches the route’s path. 318 | 319 | The `` component must have a single slot child, that will receive these props: 320 | 321 | - `history` 322 | - `location` 323 | - `match` 324 | 325 | Consider the following code: 326 | 327 | ```js 328 | import { BrowserRouter as Router, Route } from 'vue-route-lite'; 329 | 330 | const App = { 331 | components: { 332 | Router, 333 | Route 334 | }, 335 | template: ` 336 | 337 |
338 | 339 | 340 | 341 | 342 | 343 | 344 |
345 |
346 | ` 347 | } 348 | ``` 349 | 350 | If the location of the app is `/` then the UI hierarchy will be something like: 351 | 352 | ```html 353 |
354 | 355 | 356 |
357 | ``` 358 | 359 | And if the location of the app is `/news` then the UI hierarchy will be: 360 | 361 | ```html 362 |
363 | 364 | 365 |
366 | ``` 367 | 368 | Props: 369 | 370 | ### path 371 | 372 | - Type: `String | String[]` 373 | 374 | Any valid URL path or array of paths that [path-to-regexp@^3.0.0](https://github.com/pillarjs/path-to-regexp) understands. 375 | 376 | Routes without a path always match. 377 | 378 | ### exact 379 | 380 | - Type: `Boolean`, 381 | - Defaults: `false` 382 | 383 | When true, will only match if the path matches the location.pathname exactly. 384 | 385 | path | location.pathname | exact | matches? 386 | ---- | --- | --- | --- 387 | /one | /one/two | true | no 388 | /one | /one/two | false | yes 389 | 390 | ### strict 391 | 392 | - Type: `Boolean`, 393 | - Defaults: `false` 394 | 395 | When true, a path that has a trailing slash will only match a location.pathname with a trailing slash. This has no effect when there are additional URL segments in the location.pathname. 396 | 397 | path | location.pathname | matches? 398 | ---- | --- | --- 399 | /one/ | /one | no 400 | /one/ | /one/ | yes 401 | /one/ | /one/two | yes 402 | 403 | Warning: strict can be used to enforce that a location.pathname has no trailing slash, but in order to do this both strict and exact must be true. 404 | 405 | path | location.pathname | matches? 406 | ---- | --- | --- 407 | /one | /one | yes 408 | /one | /one/ | no 409 | /one | /one/two | no 410 | 411 | ### sensitive 412 | 413 | - Type: `Boolean`, 414 | - Defaults: `true` 415 | 416 | Whether the paths is case sensitive? 417 | 418 | ### forceRender 419 | 420 | - Type: `Boolean`, 421 | - Defaults: `true` 422 | 423 | If true, the route component will always render whether matched, user can control the slot's show status. 424 | 425 | ```html 426 | 427 | 428 | 429 | ``` 430 | 431 | ### location 432 | 433 | - Type: `Location` 434 | 435 | A `` element tries to match its path to the current history location (usually the current browser URL). However, a location with a different pathname can also be passed for matching. 436 | 437 | This is useful in cases when you need to match a `` to a location other than the current history location. 438 | 439 | 440 | ## `` 441 | 442 | Used to prompt the user before navigating away from a page. When your application enters a state that should prevent the user from navigating away (like a form is half-filled out), render a ``. 443 | 444 | Props: 445 | 446 | ### when 447 | 448 | - Type: `Boolean`, 449 | - required 450 | 451 | Instead of conditionally rendering a `` behind a guard, you can always render it but pass `:when="true"` or `:when="false"` to prevent or allow navigation accordingly. 452 | 453 | ### message 454 | 455 | - Type: `[Function | String]`, 456 | - required 457 | 458 | The message to prompt the user with when they try to navigate away. 459 | 460 | If message is a function, it will be called with the next location and action the user is attempting to navigate to. Return a string to show a prompt to the user or true to allow the transition. 461 | 462 | 463 | ## `` 464 | 465 | Rendering a `` will navigate to a new location. The new location will override the current location in the history stack, like server-side redirects (HTTP 3xx) do. 466 | 467 | Props: 468 | 469 | ### from 470 | 471 | - Type: `String` 472 | 473 | A pathname to redirect from. Any valid URL path that [path-to-regexp@^3.0.0](https://github.com/pillarjs/path-to-regexp) understands. All matched URL parameters are provided to the pattern in to. Must contain all parameters that are used in to. Additional parameters not used by to are ignored. 474 | 475 | ### to 476 | 477 | - Type: `[String | Location]`, 478 | - required 479 | 480 | The URL to redirect to. Any valid URL path that [path-to-regexp@^3.0.0](https://github.com/pillarjs/path-to-regexp) understands. All URL parameters that are used in to must be covered by from. 481 | 482 | Or a location to redirect to. pathname can be any valid URL path that [path-to-regexp@^3.0.0](https://github.com/pillarjs/path-to-regexp) understands. 483 | 484 | ### push 485 | 486 | - Type: `Boolean`, 487 | - Defaults: `false` 488 | 489 | When true, redirecting will push a new entry onto the history instead of replacing the current one. 490 | 491 | ### exact 492 | 493 | - Type: `Boolean`, 494 | - Defaults: `false` 495 | 496 | Match from exactly; equivalent to ` exact`. 497 | 498 | ### strict 499 | 500 | - Type: `Boolean`, 501 | - Defaults: `false` 502 | 503 | Match from exactly; equivalent to ` strict`. 504 | 505 | ### sensitive 506 | 507 | - Type: `Boolean`, 508 | - Defaults: `true` 509 | 510 | Match from exactly; equivalent to ` sensitive`. 511 | 512 | 513 | ## `` 514 | 515 | Renders the first child `` or `` that matches the location. 516 | 517 | How is this different than just using a bunch of `s`? 518 | 519 | `` is unique in that it renders a route exclusively. In contrast, every `` that matches the location renders inclusively. Consider this code: 520 | 521 | ```html 522 | 523 | 524 | 525 | ``` 526 | 527 | If the URL is `/about`, then ``, ``, and `` will all render because they all match the path. This is by design, allowing us to compose `s` into our apps in many ways, like sidebars and breadcrumbs, bootstrap tabs, etc. 528 | 529 | Occasionally, however, we want to pick only one `` to render. If we’re at `/about` we don’t want to also match `/:user` (or show our “404” page). Here’s how to do it with ``: 530 | 531 | ```html 532 | 533 | 534 | 535 | 536 | 537 | 538 | ``` 539 | 540 | Now, if we’re at `/about`, `` will start looking for a matching ``. `` will match and `` will stop looking for matches and render ``. Similarly, if we’re at `/michael` then `` will render. 541 | 542 | Props: 543 | 544 | ### keepAlive 545 | 546 | - Type: `Boolean`, 547 | - Defaults: `false` 548 | 549 | Weather keep alive the route's components, it will add a `keep-alive` component to wrap the components rendered from matched route. 550 | 551 | If the `router-switch` not remount, all the matched components in it will be cached. 552 | 553 | ```html 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | ``` 568 | 569 | ### location 570 | 571 | - Type: `Location` 572 | 573 | A `location` object to be used for matching children elements instead of the current history location (usually the current browser URL). 574 | 575 | ## `` 576 | 577 | Provides declarative, accessible navigation around your application. 578 | 579 | Props: 580 | 581 | ### to 582 | 583 | - Type: `String | Location` 584 | - Required 585 | 586 | A string representation of the location to link to, created by concatenating the location’s pathname, search, and hash properties. 587 | 588 | Or an object that can have same properties of `Location`. 589 | 590 | ### replace 591 | 592 | - Type: `Boolean` 593 | - Defaults: `false` 594 | 595 | When true, clicking the link will replace the current entry in the history stack instead of adding a new one. 596 | 597 | ### tag 598 | 599 | - Type: `String`, 600 | - Defaults: `'a'` 601 | 602 | Sometimes we want `` to render as another tag, e.g `
  • `. Then we can use tag prop to specify which tag to render to, and it will still listen to click events for navigation. 603 | 604 | ### exact 605 | 606 | - Type: `Boolean`, 607 | - Defaults: `false` 608 | 609 | When true, the active class will only be applied if the location is matched exactly. See the `` documentation for more information. 610 | 611 | ### strict 612 | 613 | - Type: `Boolean`, 614 | - Defaults: `false` 615 | 616 | When true, the trailing slash on a location’s pathname will be taken into consideration when determining if the location matches the current URL. See the `` documentation for more information. 617 | 618 | ### sensitive 619 | 620 | - Type: `Boolean`, 621 | - Defaults: `true` 622 | 623 | Whether the paths is case sensitive. See the `` documentation for more information. 624 | 625 | ### active-class 626 | 627 | - Type: `String`, 628 | - Defaults: `'router-link-active'` 629 | 630 | Configure the active CSS class applied when the link is active. 631 | 632 | ### exact-active-class 633 | 634 | - Type: `String`, 635 | - Defaults: `'router-link-exact-active'` 636 | 637 | Configure the active CSS class applied when the link is active with exact match. 638 | 639 | ### event 640 | 641 | - Type: `String | String[]`, 642 | - Defaults: `'click'` 643 | 644 | Specify the event(s) that can trigger the link navigation. 645 | 646 | ### location 647 | 648 | - Type: `location` 649 | 650 | The `isActive` compares the current history location (usually the current browser URL). To compare to a different location, a location can be passed. 651 | 652 | 653 | ## history 654 | 655 | The term “history” and "history object" in this documentation refers to the [history package](https://github.com/ReactTraining/history), which is one of only 2 major dependencies of `vue-route-lite`, and which provides several different implementations for managing session history in JavaScript in various environments. 656 | 657 | The following terms are also used: 658 | 659 | - “browser history” - A DOM-specific implementation, useful in web browsers that support the HTML5 history API 660 | - “hash history” - A DOM-specific implementation for legacy web browsers 661 | - “memory history” - An in-memory history implementation, useful in testing and non-DOM environments. 662 | 663 | history objects typically have the following properties and methods: 664 | 665 | - length - (number) The number of entries in the history stack 666 | - action - (string) The current action (PUSH, REPLACE, or POP) 667 | - location - (object) The current location. May have the following properties: 668 | - pathname - (string) The path of the URL 669 | - search - (string) The URL query string 670 | - hash - (string) The URL hash fragment 671 | - state - (object) location-specific state that was provided to e.g. push(path, state) when this location was pushed onto the stack. Only available in browser and memory history. 672 | - push(path, [state]) - (function) Pushes a new entry onto the history stack 673 | - replace(path, [state]) - (function) Replaces the current entry on the history stack 674 | - go(n) - (function) Moves the pointer in the history stack by n entries 675 | - goBack() - (function) Equivalent to go(-1) 676 | - goForward() - (function) Equivalent to go(1) 677 | - block(prompt) - (function) Prevents navigation (see the [history docs](https://github.com/ReactTraining/history#blocking-transitions)) 678 | 679 | ### history is mutable 680 | 681 | The history object is mutable. Therefore it is recommended to access the location from the slot props of ``, not from history.location. 682 | 683 | ## location 684 | 685 | Locations represent where the app is now, where you want it to go, or even where it was. It looks like this: 686 | 687 | ```js 688 | { 689 | key: 'ac3df4', // not with HashHistory! 690 | pathname: '/somewhere' 691 | search: '?some=search-string', 692 | hash: '#howdy', 693 | state: { 694 | [userDefined]: true 695 | } 696 | } 697 | ``` 698 | 699 | The router will provide you with a location object in a few places: 700 | 701 | - ` ` 702 | - ` ` 703 | 704 | ## match 705 | 706 | A match object contains information about how a `` matched the URL. match objects contain the following properties: 707 | 708 | - params - (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path 709 | - isExact - (boolean) true if the entire URL was matched (no trailing characters) 710 | - path - (string) The path pattern used to match. Useful for building nested ``s 711 | - url - (string) The matched portion of the URL. Useful for building nested ``s 712 | 713 | You’ll have access to match objects in various places: 714 | 715 | - ` ` 716 | - ` ` 717 | 718 | If a Route does not have a path, and therefore always matches, you’ll get the closest parent match. Same goes for withRouter. 719 | 720 | ## createBrowserHistory 721 | 722 | Read `createBrowserHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 723 | 724 | Useful in use with `` 725 | 726 | ## createHashHistory 727 | 728 | Read `createHashHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 729 | 730 | Useful in use with `` 731 | 732 | 733 | ## createMemoryHistory 734 | 735 | Read `createMemoryHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 736 | 737 | Useful in use with `` 738 | 739 | ## createStaticHistory 740 | 741 | Read `createStaticHistory` section on [Hisotry](https://github.com/ReactTraining/history#usage) for more details. 742 | 743 | Useful in use with `` 744 | 745 | ## matchPath 746 | 747 | This lets you use the same matching code that `` uses except outside of the normal render cycle, like gathering up data dependencies before rendering on the server. 748 | 749 | `const match = matchPath(pathname, props)`. 750 | 751 | ```js 752 | import { matchPath } from "vue-router-lite"; 753 | 754 | const match = matchPath("/users/123", { 755 | path: "/users/:id", 756 | exact: true, 757 | strict: false, 758 | sensitive: true 759 | }); 760 | ``` 761 | 762 | ### pathname 763 | 764 | The first argument is the pathname you want to match. If you’re using this on the server with Node.js, it would be req.path. 765 | 766 | ### props 767 | 768 | The second argument are the props to match against, they are identical to the matching props Route accepts: 769 | 770 | ```js 771 | { 772 | path, // like /users/:id; either a single string or an array of strings 773 | strict, // optional, defaults to false 774 | exact, // optional, defaults to false 775 | sensitive, // optional, defaults to true 776 | } 777 | ``` 778 | 779 | ### returns 780 | 781 | It returns an object when provided pathname does match path prop or null otherwise. 782 | 783 | 784 | ## generatePath 785 | 786 | generate a path with a `path` and `params`. 787 | 788 | ```js 789 | const pathname = generatePath('/user/:id', { id: 123 }); 790 | ``` 791 | 792 | Read more details at [path-to-regexp compile](https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp); -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | > `vue-router-lite` is a component-based router for vue.js, so all the features of it can do with it's components, just like use ohter general components. 4 | 5 | ## Use Components 6 | 7 | ### Global Registration 8 | 9 | If you use `Vue.use` to `Global Registration` like this, you can use those components directly: 10 | 11 | ```js 12 | import Vue from 'vue' 13 | import VueRouter from 'vue-router-lite' 14 | 15 | // register the components to global 16 | Vue.use(VueRouter) 17 | ``` 18 | 19 | It will install itself automatically when using global script tags. 20 | 21 | ### Manual import 22 | 23 | If you use `vue-router-lite` with package tools like `webpack` and `npm`, you can manual import these components and use them. 24 | 25 | ```js 26 | import Vue from 'vue' 27 | import { BrowserRouter, Route, RouterLink, RouteSwitch } from 'vue-router-lite' 28 | 29 | new Vue({ 30 | components: { 31 | BrowserRouter, 32 | Route, 33 | RouterLink, 34 | RouteSwitch 35 | } 36 | }) 37 | ``` 38 | 39 | ## HTML 40 | 41 | ```html 42 | 43 | 44 | 45 | 46 |
    47 |

    Hello App!

    48 |

    49 | 50 | 51 | 52 | Go to Foo 53 | Go to Bar 54 | Go to Bar 55 |

    56 | 57 | 58 | 59 | 60 |
    61 |

    Home

    62 | matched url: {{ match.url }} 63 |
    64 |
    65 | 66 |
    67 |

    About

    68 | matched url: {{ match.url }} 69 |
    70 |
    71 | 72 |
    73 |

    Other

    74 | matched url: {{ match.url }} 75 |
    76 |
    77 |
    78 |
    79 |
    80 | ``` 81 | 82 | ## JavaScript 83 | 84 | ```js 85 | const app = new Vue({ 86 | el: '#app' 87 | }); 88 | ``` 89 | 90 | The ``, ``, ``, ``, ``, `` will use [Scoped Slot Props](https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots) to provide the route info. 91 | 92 | ```html 93 | 94 | ... 95 | 96 | ``` 97 | 98 | Notice that a `` automatically gets the .router-link-active class when its target route is matched. You can learn more about it in its [API reference](./api/). 99 | 100 | You can also check out this example [live](https://jsfiddle.net/SeasonChen/akeh2fp7/7/). -------------------------------------------------------------------------------- /docs/guide/all.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Basic: BrowserRouter 4 | 5 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/basic](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/basic) 6 | 7 | ## HashRouter 8 | 9 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/hash-router](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/hash-router) 10 | 11 | ## MemoryRouter 12 | 13 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/memory-router](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/memory-router) 14 | 15 | ## StaticRouter 16 | 17 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/static-router](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/static-router) 18 | 19 | ## Control History: Router 20 | 21 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/control-history](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/control-history) 22 | 23 | ## URL Parameters 24 | 25 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/url-parameters](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/url-parameters) 26 | 27 | ## Auth Flow And Redirect 28 | 29 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/auth-flow](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/auth-flow) 30 | 31 | ## Chustom Link (Force Render Route) 32 | 33 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/custom-link](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/custom-link) 34 | 35 | ## Preventing Transitions (Prompt) 36 | 37 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/preventing-transitions](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/preventing-transitions) 38 | 39 | ## No Match (404) 40 | 41 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/no-match](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/no-match) 42 | 43 | ## Recursive Paths 44 | 45 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/recursive-paths](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/recursive-paths) 46 | 47 | ## Sidebar 48 | 49 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/sidebar](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/sidebar) 50 | 51 | ## Transitions 52 | 53 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/transitions](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/transitions) 54 | 55 | ## Keep Alive 56 | 57 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/keep-alive](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/keep-alive) 58 | 59 | ## Ambiguous Matches (RouteSwitch) 60 | 61 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/ambiguous-matches](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/ambiguous-matches) 62 | 63 | ## Route Config 64 | 65 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/route-config](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/route-config) 66 | 67 | ## Modal Gallery 1: RouteSwitch 68 | 69 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/modal-gallery](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/modal-gallery) 70 | 71 | ## Modal Gallery 2: path control 72 | 73 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/modal-gallery2](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/modal-gallery2) 74 | 75 | ## Active Links 76 | 77 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/active-links](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/active-links) 78 | 79 | ## Data Fetching 80 | 81 | [https://github.com/ccqgithub/vue-router-lite/tree/master/examples/data-fetching](https://github.com/ccqgithub/vue-router-lite/tree/master/examples/data-fetching) -------------------------------------------------------------------------------- /docs/guide/control-history.md: -------------------------------------------------------------------------------- 1 | # Control History 2 | 3 | todo -------------------------------------------------------------------------------- /docs/guide/navigation.md: -------------------------------------------------------------------------------- 1 | # Navigation 2 | 3 | todo -------------------------------------------------------------------------------- /docs/guide/preventing-transitions.md: -------------------------------------------------------------------------------- 1 | # Preventing Transitions 2 | 3 | todo -------------------------------------------------------------------------------- /docs/guide/redirects.md: -------------------------------------------------------------------------------- 1 | # Redirects 2 | 3 | todo -------------------------------------------------------------------------------- /docs/guide/route-info.md: -------------------------------------------------------------------------------- 1 | # Route Info 2 | 3 | todo -------------------------------------------------------------------------------- /docs/guide/route-matching.md: -------------------------------------------------------------------------------- 1 | # Route Matching 2 | 3 | todo -------------------------------------------------------------------------------- /docs/guide/routers.md: -------------------------------------------------------------------------------- 1 | # Routers 2 | 3 | todo -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Direct Download / CDN 4 | 5 | [https://unpkg.com/vue-router-lite/dist/vue-router-lite.umd.js](https://unpkg.com/vue-router-lite/dist/vue-router-lite.umd.js) 6 | 7 | 8 | [Unpkg.com](https://unpkg.com) provides npm-based CDN links. The above link will always point to the latest release on npm. You can also use a specific version/tag via URLs like `https://unpkg.com/vue-router-lite@1.2.1/dist/vue-router-lite.umd.js`. 9 | 10 | 11 | Include `vue-router-lite` after Vue and it will install itself automatically: 12 | 13 | ``` html 14 | 15 | 16 | ``` 17 | 18 | ## Npm 19 | 20 | ``` bash 21 | npm install vue-router-lite 22 | ``` 23 | 24 | ## Use 25 | 26 | There are two ways to use the `vue-router-lite`'s components. 27 | 28 | ### `Global Registration` via `Vue.use()` 29 | 30 | > You don't need to do `Vue.use()` when using global script tags. 31 | 32 | ``` js 33 | import Vue from 'vue' 34 | import VueRouter from 'vue-router-lite' 35 | 36 | // register the components to global 37 | Vue.use(VueRouter) 38 | 39 | // then use the components directly 40 | new Vue({ 41 | el: '#app', 42 | template: ` 43 | 44 |
    45 |
      46 |
    • 47 | Home 48 |
    • 49 |
    • 50 | About 51 |
    • 52 |
    • 53 | Topics 54 |
    • 55 |
    56 | 57 |
    58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
    69 |
    70 | ` 71 | }); 72 | ``` 73 | 74 | ### Local Registration 75 | 76 | ```js 77 | import Vue from 'vue' 78 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 79 | 80 | // then use the components directly 81 | new Vue({ 82 | components: { 83 | Router, 84 | Route, 85 | RouterLink 86 | }, 87 | el: '#app', 88 | template: ` 89 | 90 |
    91 |
      92 |
    • 93 | Home 94 |
    • 95 |
    • 96 | About 97 |
    • 98 |
    • 99 | Topics 100 |
    • 101 |
    102 | 103 |
    104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
    115 |
    116 | ` 117 | }); 118 | ``` 119 | 120 | ## Dev Build 121 | 122 | You will have to clone directly from GitHub and build `vue-router-lite` yourself if 123 | you want to use the latest dev build. 124 | 125 | ``` bash 126 | git clone https://github.com/ccqgithub/vue-router-lite/.git node_modules/vue-router-lite 127 | cd node_modules/vue-router-lite 128 | npm install 129 | npm run build 130 | ``` 131 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "docs": "vuepress dev .", 4 | "docs:build": "vuepress build ." 5 | }, 6 | "devDependencies": { 7 | "@vuepress/theme-default": "^1.0.2", 8 | "vuepress": "^1.0.2", 9 | "vuepress-theme-vue": "^1.1.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/active-links/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | import '../global.css' 4 | 5 | const Home = { template: '

    Home

    ' } 6 | const About = { template: '

    About

    ' } 7 | 8 | const User = { 9 | props: { 10 | match: { 11 | type: Object 12 | }, 13 | location: { 14 | type: Object 15 | } 16 | }, 17 | template: '
    {{ match.params.username }}
    {{location.search}}
    ' 18 | } 19 | 20 | const Users = { 21 | props: { 22 | match: { 23 | type: Object 24 | } 25 | }, 26 | components: { 27 | User, 28 | Route 29 | }, 30 | template: ` 31 |
    32 |

    Users

    33 | 34 | 37 | 38 |
    39 | ` 40 | } 41 | 42 | new Vue({ 43 | components: { 44 | Router, 45 | Route, 46 | RouterLink, 47 | Home, 48 | About, 49 | Users 50 | }, 51 | data() { 52 | const p = '/active-links'; 53 | const basename = location.pathname.split(p)[0] + p + '/'; 54 | return { 55 | basename 56 | } 57 | }, 58 | template: ` 59 | 60 |
    61 |

    Active Links

    62 |
      63 |
    • /
    • 64 |
    • / (exact match)
    • 65 | 66 |
    • /users
    • 67 |
    • /users (exact match)
    • 68 | 69 |
    • /users/evan
    • 70 |
    • /users/evan#foo
    • 71 |
    • 72 | 73 | /users/evan?foo=bar 74 | 75 |
    • 76 |
    • 77 | 78 | /users/evan?foo=bar&baz=qux 79 | 80 |
    • 81 | 82 |
    • /about
    • 83 | 84 | 85 | /about (active class on outer element) 86 | 87 |
    88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 99 | 100 |
    101 |
    102 | ` 103 | }).$mount('#app') 104 | -------------------------------------------------------------------------------- /examples/active-links/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 20 | 21 | 22 | 23 | ← Examples index 24 |
    25 | 26 | <% for (var js in htmlWebpackPlugin.files.js) { %> 27 | 28 | <% } %> 29 | 30 | -------------------------------------------------------------------------------- /examples/ambiguous-matches/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, RouteSwitch } from 'vue-router-lite' 3 | 4 | const About = { 5 | template: ` 6 |
    7 |

    About

    8 |
    9 | ` 10 | } 11 | 12 | const Company = { 13 | template: ` 14 |
    15 |

    Company

    16 |
    17 | ` 18 | } 19 | 20 | const User = { 21 | props: { 22 | match: Object 23 | }, 24 | template: ` 25 |
    26 |

    User: {{ match.params.user }}

    27 |
    28 | ` 29 | } 30 | 31 | const App = { 32 | data: () => { 33 | return { 34 | // 35 | } 36 | }, 37 | components: { 38 | Route, 39 | RouterLink, 40 | RouteSwitch, 41 | Company, 42 | About, 43 | User 44 | }, 45 | template: ` 46 |
    47 |

    Ambiguous Matches: RouteSwitch

    48 |
      49 |
    • 50 | About Us (static) 51 |
    • 52 |
    • 53 | Company (static) 54 |
    • 55 |
    • 56 | Kim (dynamic) 57 |
    • 58 |
    • 59 | Chris (dynamic) 60 |
    • 61 |
    62 | 63 |
    64 | 65 |
     66 | Sometimes you want to have a whitelist of static paths like "/about" and "/company" but also allow for dynamic patterns like "/:user". 
     67 | The problem is that "/about" is ambiguous and will match both "/about" and "/:user".
     68 | Most routers have an algorithm to decide for you what it will match since they only allow you to match one "route". 
     69 | Vue Router Lite lets you match in multiple places on purpose (sidebars, breadcrumbs, etc). 
     70 | So, when you want to clear up any ambiguous matching, and not match "/about" to "/:user", just wrap your <route>s in a <route-switch>. 
     71 | It will render the first one that matches.
     72 |       
    73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
    86 | `, 87 | 88 | methods: { 89 | // 90 | } 91 | } 92 | 93 | new Vue({ 94 | components: { 95 | App, 96 | Router 97 | }, 98 | data() { 99 | const p = '/ambiguous-matches'; 100 | const basename = location.pathname.split(p)[0] + p + '/'; 101 | return { 102 | basename 103 | } 104 | }, 105 | template: ` 106 | 107 | 108 | 109 | ` 110 | }).$mount('#app') 111 | -------------------------------------------------------------------------------- /examples/ambiguous-matches/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/auth-flow/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | import App from './components/App.vue' 5 | 6 | /* eslint-disable no-new */ 7 | new Vue({ 8 | components: { 9 | App, 10 | Router 11 | }, 12 | data() { 13 | const p = '/auth-flow'; 14 | const basename = location.pathname.split(p)[0] + p + '/'; 15 | return { 16 | basename 17 | } 18 | }, 19 | template: ` 20 | 21 | 22 | 23 | ` 24 | }).$mount('#app') -------------------------------------------------------------------------------- /examples/auth-flow/auth.js: -------------------------------------------------------------------------------- 1 | /* globals localStorage */ 2 | 3 | export default { 4 | login (email, pass, cb) { 5 | cb = arguments[arguments.length - 1] 6 | if (localStorage.token) { 7 | if (cb) cb(true) 8 | this.onChange(true) 9 | return 10 | } 11 | pretendRequest(email, pass, (res) => { 12 | if (res.authenticated) { 13 | localStorage.token = res.token 14 | if (cb) cb(true) 15 | this.onChange(true) 16 | } else { 17 | if (cb) cb(false) 18 | this.onChange(false) 19 | } 20 | }) 21 | }, 22 | 23 | getToken () { 24 | return localStorage.token 25 | }, 26 | 27 | logout (cb) { 28 | delete localStorage.token 29 | if (cb) cb() 30 | this.onChange(false) 31 | }, 32 | 33 | loggedIn () { 34 | return !!localStorage.token 35 | }, 36 | 37 | onChange () {} 38 | } 39 | 40 | function pretendRequest (email, pass, cb) { 41 | setTimeout(() => { 42 | if (email === 'joe@example.com' && pass === 'password1') { 43 | cb({ 44 | authenticated: true, 45 | token: Math.random().toString(36).substring(7) 46 | }) 47 | } else { 48 | cb({ authenticated: false }) 49 | } 50 | }, 0) 51 | } 52 | -------------------------------------------------------------------------------- /examples/auth-flow/components/About.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /examples/auth-flow/components/App.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 92 | -------------------------------------------------------------------------------- /examples/auth-flow/components/CheckLogin.vue: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /examples/auth-flow/components/Dashboard.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /examples/auth-flow/components/Login.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 56 | 57 | 62 | -------------------------------------------------------------------------------- /examples/auth-flow/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/basic/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router-lite' 3 | 4 | Vue.use(VueRouter) 5 | 6 | const Home = { 7 | template: ` 8 |
    9 |

    Home

    10 |
    11 | ` 12 | } 13 | 14 | const About = { 15 | template: ` 16 |
    17 |

    About

    18 |
    19 | ` 20 | } 21 | 22 | const Topic = { 23 | props: { 24 | topicId: { 25 | type: String, 26 | required: true 27 | } 28 | }, 29 | template: ` 30 |
    31 |

    {{ topicId }}

    32 |
    33 | ` 34 | } 35 | 36 | const Topics = { 37 | components: { 38 | Topic 39 | }, 40 | props: { 41 | match: { 42 | type: Object, 43 | required: true 44 | } 45 | }, 46 | mounted() { 47 | // console.log(this.match) 48 | }, 49 | template: ` 50 |
    51 |

    Topics

    52 |
      53 |
    • 54 | Rendering 55 |
    • 56 |
    • 57 | Components 58 |
    • 59 |
    • 60 | Props v. State 61 |
    • 62 |
    63 | 64 | 68 | 69 | 70 | 74 |

    Please select a topic.

    75 |
    76 |
    77 | ` 78 | } 79 | 80 | const App = { 81 | data: () => { 82 | return { 83 | // 84 | } 85 | }, 86 | components: { 87 | Topics, 88 | About, 89 | Home 90 | }, 91 | template: ` 92 |
    93 |

    Basic: BrowserRouter

    94 |
      95 |
    • 96 | Home 97 |
    • 98 |
    • 99 | About 100 |
    • 101 |
    • 102 | Topics 103 |
    • 104 |
    105 | 106 |
    107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
    118 | `, 119 | 120 | methods: { 121 | // 122 | } 123 | } 124 | 125 | new Vue({ 126 | components: { 127 | App 128 | }, 129 | data() { 130 | const p = '/basic'; 131 | const basename = location.pathname.split(p)[0] + p + '/'; 132 | return { 133 | basename 134 | } 135 | }, 136 | template: ` 137 | 138 | 139 | 140 | ` 141 | }).$mount('#app') 142 | -------------------------------------------------------------------------------- /examples/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/control-history/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { Router, Route, RouterLink, createBrowserHistory } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |
    7 |

    Home

    8 |
    9 | ` 10 | } 11 | 12 | const About = { 13 | template: ` 14 |
    15 |

    About

    16 |
    17 | ` 18 | } 19 | 20 | const Topic = { 21 | props: { 22 | topicId: { 23 | type: String, 24 | required: true 25 | } 26 | }, 27 | template: ` 28 |
    29 |

    {{ topicId }}

    30 |
    31 | ` 32 | } 33 | 34 | const Topics = { 35 | components: { 36 | RouterLink, 37 | Topic, 38 | Route 39 | }, 40 | props: { 41 | match: { 42 | type: Object, 43 | required: true 44 | } 45 | }, 46 | mounted() { 47 | // console.log(this.match) 48 | }, 49 | template: ` 50 |
    51 |

    Topics

    52 |
      53 |
    • 54 | Rendering 55 |
    • 56 |
    • 57 | Components 58 |
    • 59 |
    • 60 | Props v. State 61 |
    • 62 |
    63 | 64 | 65 | 66 | 67 | 71 |

    Please select a topic.

    72 |
    73 |
    74 | ` 75 | } 76 | 77 | const App = { 78 | data: () => ({ n: 0 }), 79 | components: { 80 | Route, 81 | RouterLink, 82 | Home, 83 | About, 84 | Topics 85 | }, 86 | template: ` 87 |
    88 |

    Control History: Router

    89 |
    Redirect to topics after 5 seconds.
    90 |
      91 |
    • 92 | Home 93 |
    • 94 |
    • 95 | About 96 |
    • 97 |
    • 98 | Topics 99 |
    • 100 |
    101 | 102 |
    103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 |
    114 | `, 115 | 116 | methods: { 117 | // 118 | } 119 | } 120 | 121 | const p = '/control-history'; 122 | const basename = location.pathname.split(p)[0] + p + '/'; 123 | const history = createBrowserHistory({ 124 | basename 125 | }) 126 | 127 | new Vue({ 128 | components: { 129 | App, 130 | Router 131 | }, 132 | data() { 133 | return { 134 | history 135 | } 136 | }, 137 | template: ` 138 | 139 | 140 | 141 | ` 142 | }).$mount('#app') 143 | 144 | setTimeout(() => { 145 | history.push('/topics/rendering'); 146 | }, 5000); 147 | -------------------------------------------------------------------------------- /examples/control-history/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/custom-link/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |
    7 |

    Home

    8 |
    9 | ` 10 | } 11 | 12 | const About = { 13 | template: ` 14 |
    15 |

    About

    16 |
    17 | ` 18 | } 19 | 20 | const OldSchoolMenuLink = { 21 | components: { 22 | Route, 23 | RouterLink 24 | }, 25 | props: { 26 | label: String, 27 | to: [String, Object], 28 | activeOnlyWhenExact: Boolean, 29 | }, 30 | template: ` 31 | 32 |
    33 | {{ match ? '> ' : '' }} 34 | {{ label }} 35 |
    36 |
    37 | ` 38 | } 39 | 40 | const App = { 41 | data: () => ({ n: 0 }), 42 | components: { 43 | Route, 44 | RouterLink, 45 | Home, 46 | About, 47 | OldSchoolMenuLink 48 | }, 49 | template: ` 50 |
    51 |

    custom link

    52 |
    53 | 54 | 55 |
    56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | `, 65 | 66 | methods: { 67 | // 68 | } 69 | } 70 | 71 | new Vue({ 72 | components: { 73 | App, 74 | Router 75 | }, 76 | data() { 77 | const p = '/custom-link'; 78 | const basename = location.pathname.split(p)[0] + p + '/'; 79 | return { 80 | basename 81 | } 82 | }, 83 | template: ` 84 | 85 | 86 | 87 | ` 88 | }).$mount('#app') 89 | -------------------------------------------------------------------------------- /examples/custom-link/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/data-fetching/Post.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 56 | 57 | 79 | -------------------------------------------------------------------------------- /examples/data-fetching/api.js: -------------------------------------------------------------------------------- 1 | const posts = { 2 | '1': { 3 | id: 1, 4 | title: 'sunt aut facere', 5 | body: 'quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto' 6 | }, 7 | '2': { 8 | id: 2, 9 | title: 'qui est esse', 10 | body: 'est rerum tempore vitae sequi sint nihil reprehenderit dolor beatae ea dolores neque fugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis qui aperiam non debitis possimus qui neque nisi nulla' 11 | } 12 | } 13 | 14 | export function getPost (id, cb) { 15 | // fake an API request 16 | setTimeout(() => { 17 | if (posts[id]) { 18 | cb(null, posts[id]) 19 | } else { 20 | cb(new Error('Post not found.')) 21 | } 22 | }, 100) 23 | } 24 | -------------------------------------------------------------------------------- /examples/data-fetching/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | import Post from './Post.vue' 4 | 5 | const Home = { template: '
    home
    ' } 6 | 7 | new Vue({ 8 | components: { 9 | Router, 10 | Route, 11 | RouterLink, 12 | Home, 13 | Post 14 | }, 15 | data() { 16 | const p = '/data-fetching'; 17 | const basename = location.pathname.split(p)[0] + p + '/'; 18 | return { 19 | basename 20 | } 21 | }, 22 | template: ` 23 | 24 |
    25 |

    Data Fetching

    26 |
      27 |
    • /
    • 28 |
    • /post/1
    • 29 |
    • /post/2
    • 30 |
    • /post/3
    • 31 |
    32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | ` 43 | }).$mount('#app') 44 | -------------------------------------------------------------------------------- /examples/data-fetching/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/global.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 3 | color: #2c3e50; 4 | } 5 | 6 | #app { 7 | padding: 0 20px; 8 | } 9 | 10 | ul { 11 | line-height: 1.5em; 12 | padding-left: 1.5em; 13 | } 14 | 15 | a { 16 | color: #489774; 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | color: #4fc08d; 22 | } 23 | -------------------------------------------------------------------------------- /examples/hash-router/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { HashRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |
    7 |

    Home

    8 |
    9 | ` 10 | } 11 | 12 | const About = { 13 | template: ` 14 |
    15 |

    About

    16 |
    17 | ` 18 | } 19 | 20 | const Topic = { 21 | props: { 22 | topicId: { 23 | type: String, 24 | required: true 25 | } 26 | }, 27 | template: ` 28 |
    29 |

    {{ topicId }}

    30 |
    31 | ` 32 | } 33 | 34 | const Topics = { 35 | components: { 36 | RouterLink, 37 | Topic, 38 | Route 39 | }, 40 | props: { 41 | match: { 42 | type: Object, 43 | required: true 44 | } 45 | }, 46 | mounted() { 47 | // console.log(this.match) 48 | }, 49 | template: ` 50 |
    51 |

    Topics

    52 |
      53 |
    • 54 | Rendering 55 |
    • 56 |
    • 57 | Components 58 |
    • 59 |
    • 60 | Props v. State 61 |
    • 62 |
    63 | 64 | 65 | 66 | 67 | 68 |

    Please select a topic.

    69 |
    70 |
    71 | ` 72 | } 73 | 74 | const App = { 75 | data: () => ({ n: 0 }), 76 | components: { 77 | Route, 78 | RouterLink, 79 | Home, 80 | About, 81 | Topics 82 | }, 83 | template: ` 84 |
    85 |

    Basic: BrowserRouter

    86 |
      87 |
    • 88 | Home 89 |
    • 90 |
    • 91 | About 92 |
    • 93 |
    • 94 | Topics 95 |
    • 96 |
    97 | 98 |
    99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 |
    110 | `, 111 | 112 | methods: { 113 | // 114 | } 115 | } 116 | 117 | new Vue({ 118 | components: { 119 | App, 120 | Router 121 | }, 122 | template: ` 123 | 124 | 125 | 126 | ` 127 | }).$mount('#app') 128 | -------------------------------------------------------------------------------- /examples/hash-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vue Router Lite Examples 8 | 9 | <% for (var css in htmlWebpackPlugin.files.css) { %> 10 | 11 | <% } %> 12 | 13 | 14 |

    Vue Router Lite Examples

    15 | 37 | 38 | <% for (var js in htmlWebpackPlugin.files.js) { %> 39 | 40 | <% } %> 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/keep-alive/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, RouteSwitch } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |
    7 |

    Home

    8 |
    9 |
    10 | ` 11 | } 12 | 13 | const Alive = { 14 | template: ` 15 |
    16 |

    Keep Alive Component

    17 |
    18 |
    19 | ` 20 | } 21 | 22 | const AliveChild = { 23 | props: { 24 | id: { 25 | type: String, 26 | required: true 27 | } 28 | }, 29 | template: ` 30 |
    31 |

    Nested Keep Alive Child: {{ id }}

    32 |
    33 |
    34 | ` 35 | } 36 | 37 | const NestAlive = { 38 | components: { 39 | RouteSwitch, 40 | RouterLink, 41 | Route, 42 | AliveChild 43 | }, 44 | props: { 45 | match: { 46 | type: Object, 47 | required: true 48 | } 49 | }, 50 | template: ` 51 |
    52 |

    Nested Keep Alive Parent

    53 |
      54 |
    • 55 | Keep Alive Child A 56 |
    • 57 |
    • 58 | Keep Alive Child B 59 |
    • 60 |
    • 61 | Not Keep Alive Child C 62 |
    • 63 |
    64 | 65 | 66 | 67 |
    68 | 69 | 70 | 74 | 78 | 79 | 80 | 81 | 85 |

    86 | without keep alive 87 |

    88 |
    89 | 90 | 91 | 96 |

    97 | defautl route: 98 | 99 |

    100 |
    101 |
    102 |
    103 | ` 104 | } 105 | 106 | const App = { 107 | data: () => { 108 | return { 109 | // 110 | } 111 | }, 112 | components: { 113 | Route, 114 | RouterLink, 115 | RouteSwitch, 116 | Home, 117 | Alive, 118 | NestAlive 119 | }, 120 | template: ` 121 |
    122 |

    Keep Alive (RouteSwitch)

    123 |
      124 |
    • 125 | Home 126 |
    • 127 |
    • 128 | Keep Alive Route 129 |
    • 130 |
    • 131 | Nested Keep Alive Route 132 |
    • 133 |
    134 | 135 |
    136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |
    151 | `, 152 | 153 | methods: { 154 | // 155 | } 156 | } 157 | 158 | new Vue({ 159 | components: { 160 | App, 161 | Router 162 | }, 163 | data() { 164 | const p = '/keep-alive'; 165 | const basename = location.pathname.split(p)[0] + p + '/'; 166 | return { 167 | basename 168 | } 169 | }, 170 | template: ` 171 | 172 | 173 | 174 | ` 175 | }).$mount('#app') 176 | -------------------------------------------------------------------------------- /examples/keep-alive/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/memory-router/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { MemoryRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |
    7 |

    Home

    8 |
    9 | ` 10 | } 11 | 12 | const About = { 13 | template: ` 14 |
    15 |

    About

    16 |
    17 | ` 18 | } 19 | 20 | const Topic = { 21 | props: { 22 | topicId: { 23 | type: String, 24 | required: true 25 | } 26 | }, 27 | template: ` 28 |
    29 |

    {{ topicId }}

    30 |
    31 | ` 32 | } 33 | 34 | const Topics = { 35 | components: { 36 | RouterLink, 37 | Topic, 38 | Route 39 | }, 40 | props: { 41 | match: { 42 | type: Object, 43 | required: true 44 | } 45 | }, 46 | mounted() { 47 | // console.log(this.match) 48 | }, 49 | template: ` 50 |
    51 |

    Topics

    52 |
      53 |
    • 54 | Rendering 55 |
    • 56 |
    • 57 | Components 58 |
    • 59 |
    • 60 | Props v. State 61 |
    • 62 |
    63 | 64 | > 65 | 66 | 67 | 71 |

    Please select a topic.

    72 |
    73 |
    74 | ` 75 | } 76 | 77 | const App = { 78 | data: () => ({ n: 0 }), 79 | components: { 80 | Route, 81 | RouterLink, 82 | Home, 83 | About, 84 | Topics 85 | }, 86 | template: ` 87 |
    88 |

    MemoryRouter

    89 |
      90 |
    • 91 | Home 92 |
    • 93 |
    • 94 | About 95 |
    • 96 |
    • 97 | Topics 98 |
    • 99 |
    100 | 101 |
    102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 |
    113 | `, 114 | 115 | methods: { 116 | // 117 | } 118 | } 119 | 120 | new Vue({ 121 | components: { 122 | App, 123 | Router 124 | }, 125 | data() { 126 | const p = '/memory-router'; 127 | const basename = location.pathname.split(p)[0] + p + '/'; 128 | return { 129 | basename 130 | } 131 | }, 132 | template: ` 133 | 134 | 135 | 136 | ` 137 | }).$mount('#app') 138 | -------------------------------------------------------------------------------- /examples/memory-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/modal-gallery/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, RouteSwitch } from 'vue-router-lite' 3 | 4 | // This example shows how to render two different screens 5 | // (or the same screen in a different context) at the same url, 6 | // depending on how you got there. 7 | // 8 | // Click the colors and see them full screen, then "visit the 9 | // gallery" and click on the colors. Note the URL and the component 10 | // are the same as before but now we see them inside a modal 11 | // on top of the old screen. 12 | 13 | const IMAGES = [ 14 | { id: 0, title: "Dark Orchid", color: "DarkOrchid" }, 15 | { id: 1, title: "Lime Green", color: "LimeGreen" }, 16 | { id: 2, title: "Tomato", color: "Tomato" }, 17 | { id: 3, title: "Seven Ate Nine", color: "#789" }, 18 | { id: 4, title: "Crimson", color: "Crimson" } 19 | ]; 20 | 21 | const Thumbnail = { 22 | props: { 23 | color: String 24 | }, 25 | template: ` 26 |
    33 | ` 34 | } 35 | 36 | const ImageShow = { 37 | props: { 38 | color: String 39 | }, 40 | template: ` 41 |
    48 | ` 49 | } 50 | 51 | const Home = { 52 | components: { 53 | RouterLink 54 | }, 55 | template: ` 56 |
    57 | Visit the Gallery 58 |

    Featured Images

    59 |
      60 |
    • 61 | Tomato 62 |
    • 63 |
    • 64 | Crimson 65 |
    • 66 |
    67 |
    68 | ` 69 | } 70 | 71 | const Gallery = { 72 | components: { 73 | RouterLink, 74 | Thumbnail 75 | }, 76 | data() { 77 | return { 78 | IMAGES 79 | } 80 | }, 81 | template: ` 82 |
    83 | 91 | 92 |

    {{ item.title }}

    93 |
    94 |
    95 | ` 96 | } 97 | 98 | const ImageView = { 99 | components: { 100 | ImageShow 101 | }, 102 | props: { 103 | match: Object 104 | }, 105 | computed: { 106 | image() { 107 | return IMAGES[parseInt(this.match.params.id, 10)]; 108 | } 109 | }, 110 | template: ` 111 |
    Image not found
    112 |
    113 |

    {{ image.title }}

    114 | 115 |
    116 | ` 117 | } 118 | 119 | const Modal = { 120 | components: { 121 | ImageShow 122 | }, 123 | props: { 124 | history: Object, 125 | match: Object 126 | }, 127 | computed: { 128 | image() { 129 | return IMAGES[parseInt(this.match.params.id, 10)]; 130 | } 131 | }, 132 | methods: { 133 | back(e) { 134 | e.stopPropagation(); 135 | this.history.goBack(); 136 | } 137 | }, 138 | template: ` 139 |
    150 | 168 |
    169 | ` 170 | } 171 | 172 | // We can pass a location to that will tell it to 173 | // ignore the router's current location and use the location 174 | // prop instead. 175 | // 176 | // We can also use "location state" to tell the app the user 177 | // wants to go to `/img/2` in a modal, rather than as the 178 | // main page, keeping the gallery visible behind it. 179 | // 180 | // Normally, `/img/2` wouldn't match the gallery at `/`. 181 | // So, to get both screens to render, we can save the old 182 | // location and pass it to RouteSwitch, so it will think the location 183 | // is still `/` even though its `/img/2`. 184 | const App = { 185 | components: { 186 | Route, 187 | RouteSwitch, 188 | Home, 189 | Gallery, 190 | ImageView, 191 | Modal 192 | }, 193 | props: { 194 | location: Object, 195 | history: Object 196 | }, 197 | data() { 198 | return { 199 | previousLocation: this.location 200 | } 201 | }, 202 | computed: { 203 | isModal() { 204 | let { location } = this; 205 | let isModal = !!( 206 | location.state && 207 | location.state.modal && 208 | this.previousLocation !== location 209 | ); 210 | return isModal; 211 | } 212 | }, 213 | watch: { 214 | 'history': { 215 | handler(history, oldHistory) { 216 | if ( 217 | history.action !== "POP" && 218 | (!history.location.state || !history.location.state.modal) 219 | ) { 220 | this.previousLocation = history.location; 221 | } 222 | }, 223 | deep: true 224 | } 225 | }, 226 | template: ` 227 |
    228 |

    Modal Gallery 1: RouteSwitch

    229 |
    230 | 231 | 236 | 237 | 238 | 242 | 243 | 244 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 |
    256 | ` 257 | } 258 | 259 | new Vue({ 260 | components: { 261 | App, 262 | Router 263 | }, 264 | data() { 265 | const p = '/modal-gallery'; 266 | const basename = location.pathname.split(p)[0] + p + '/'; 267 | return { 268 | basename 269 | } 270 | }, 271 | template: ` 272 | 273 | 274 | 275 | ` 276 | }).$mount('#app') 277 | -------------------------------------------------------------------------------- /examples/modal-gallery/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/modal-gallery2/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, RouteSwitch } from 'vue-router-lite' 3 | 4 | // This example shows how to render two different screens 5 | // (or the same screen in a different context) at the same url, 6 | // depending on how you got there. 7 | // 8 | // Click the colors and see them full screen, then "visit the 9 | // gallery" and click on the colors. Note the URL and the component 10 | // are the same as before but now we see them inside a modal 11 | // on top of the old screen. 12 | 13 | const IMAGES = [ 14 | { id: 0, title: "Dark Orchid", color: "DarkOrchid" }, 15 | { id: 1, title: "Lime Green", color: "LimeGreen" }, 16 | { id: 2, title: "Tomato", color: "Tomato" }, 17 | { id: 3, title: "Seven Ate Nine", color: "#789" }, 18 | { id: 4, title: "Crimson", color: "Crimson" } 19 | ]; 20 | 21 | const Thumbnail = { 22 | props: { 23 | color: String 24 | }, 25 | template: ` 26 |
    33 | ` 34 | } 35 | 36 | const ImageShow = { 37 | props: { 38 | color: String 39 | }, 40 | template: ` 41 |
    48 | ` 49 | } 50 | 51 | const Home = { 52 | components: { 53 | RouterLink 54 | }, 55 | template: ` 56 |
    57 | Visit the Gallery 58 |

    Featured Images

    59 |
      60 |
    • 61 | Tomato 62 |
    • 63 |
    • 64 | Crimson 65 |
    • 66 |
    67 |
    68 | ` 69 | } 70 | 71 | const Gallery = { 72 | components: { 73 | RouterLink, 74 | Thumbnail 75 | }, 76 | data() { 77 | return { 78 | IMAGES 79 | } 80 | }, 81 | template: ` 82 |
    83 | 88 | 89 |

    {{ item.title }}

    90 |
    91 |
    92 | ` 93 | } 94 | 95 | const ImageView = { 96 | components: { 97 | ImageShow 98 | }, 99 | props: { 100 | match: Object 101 | }, 102 | computed: { 103 | image() { 104 | return IMAGES[parseInt(this.match.params.id, 10)]; 105 | } 106 | }, 107 | template: ` 108 |
    Image not found
    109 |
    110 |

    {{ image.title }}

    111 | 112 |
    113 | ` 114 | } 115 | 116 | const Modal = { 117 | components: { 118 | ImageShow 119 | }, 120 | props: { 121 | history: Object, 122 | match: Object 123 | }, 124 | computed: { 125 | image() { 126 | return IMAGES[parseInt(this.match.params.id, 10)]; 127 | } 128 | }, 129 | methods: { 130 | back(e) { 131 | e.stopPropagation(); 132 | this.history.goBack(); 133 | } 134 | }, 135 | template: ` 136 |
    147 | 165 |
    166 | ` 167 | } 168 | 169 | // We can pass a location to that will tell it to 170 | // ignore the router's current location and use the location 171 | // prop instead. 172 | // 173 | // We can also use "location state" to tell the app the user 174 | // wants to go to `/img/2` in a modal, rather than as the 175 | // main page, keeping the gallery visible behind it. 176 | // 177 | // Normally, `/img/2` wouldn't match the gallery at `/`. 178 | // So, to get both screens to render, we can save the old 179 | // location and pass it to RouteSwitch, so it will think the location 180 | // is still `/` even though its `/img/2`. 181 | const App = { 182 | components: { 183 | Route, 184 | RouteSwitch, 185 | Home, 186 | Gallery, 187 | ImageView, 188 | Modal 189 | }, 190 | props: { 191 | location: Object, 192 | history: Object 193 | }, 194 | data() { 195 | return { 196 | previousLocation: this.location 197 | } 198 | }, 199 | computed: { 200 | isModal() { 201 | let { location } = this; 202 | let isModal = !!( 203 | location.state && 204 | location.state.modal && 205 | this.previousLocation !== location 206 | ); 207 | return isModal; 208 | } 209 | }, 210 | watch: { 211 | 'history': { 212 | handler(history, oldHistory) { 213 | if ( 214 | history.action !== "POP" && 215 | (!history.location.state || !history.location.state.modal) 216 | ) { 217 | this.previousLocation = history.location; 218 | } 219 | }, 220 | deep: true 221 | } 222 | }, 223 | template: ` 224 |
    225 |

    Modal Gallery 2: path control

    226 |
    227 | 228 | 233 | 234 | 235 | 239 | 240 | 241 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 |
    253 | ` 254 | } 255 | 256 | new Vue({ 257 | components: { 258 | App, 259 | Router 260 | }, 261 | data() { 262 | const p = '/modal-gallery2'; 263 | const basename = location.pathname.split(p)[0] + p + '/'; 264 | return { 265 | basename 266 | } 267 | }, 268 | template: ` 269 | 270 | 271 | 272 | ` 273 | }).$mount('#app') 274 | -------------------------------------------------------------------------------- /examples/modal-gallery2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/no-match/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, Redirect, RouteSwitch } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |

    7 | A <route-switch> renders the first child <route>{{" "}} 8 | that matches. A <route> with no path always 9 | matches. 10 |

    11 | ` 12 | } 13 | 14 | const WillMatch = { 15 | template: ` 16 |

    Matched!

    17 | ` 18 | } 19 | 20 | const NoMatch = { 21 | props: { 22 | location: { 23 | type: Object 24 | } 25 | }, 26 | template: ` 27 |
    28 |

    29 | No match for {{ location.pathname }} 30 |

    31 |
    32 | ` 33 | } 34 | 35 | const App = { 36 | data: () => ({ n: 0 }), 37 | components: { 38 | Route, 39 | RouterLink, 40 | Redirect, 41 | RouteSwitch, 42 | Home, 43 | WillMatch, 44 | NoMatch, 45 | }, 46 | template: ` 47 |
    48 |

    No Match (404)

    49 |
    50 |
      51 |
    • 52 | Home 53 |
    • 54 |
    • 55 | Old Match, to be redirected 56 |
    • 57 |
    • 58 | Will Match 59 |
    • 60 |
    • 61 | Will Not Match 62 |
    • 63 |
    • 64 | Also Will Not Match 65 |
    • 66 |
    67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
    82 |
    83 | `, 84 | 85 | methods: { 86 | // 87 | } 88 | } 89 | 90 | new Vue({ 91 | components: { 92 | App, 93 | Router 94 | }, 95 | data() { 96 | const p = '/no-match'; 97 | const basename = location.pathname.split(p)[0] + p + '/'; 98 | return { 99 | basename 100 | } 101 | }, 102 | template: ` 103 | 104 | 105 | 106 | ` 107 | }).$mount('#app') 108 | -------------------------------------------------------------------------------- /examples/no-match/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/preventing-transitions/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, Prompt } from 'vue-router-lite' 3 | 4 | const FormExample = { 5 | components: { 6 | RouterLink, 7 | Route, 8 | Prompt 9 | }, 10 | data() { 11 | return { 12 | isBlocking: false 13 | } 14 | }, 15 | methods: { 16 | onSubmit(event) { 17 | event.preventDefault(); 18 | event.target.reset(); 19 | this.isBlocking = false; 20 | }, 21 | onBlock(location, action) { 22 | return `Are you sure you want to go to ${location.pathname}`; 23 | }, 24 | onInputChange(event) { 25 | this.isBlocking = event.target.value.length > 0; 26 | } 27 | }, 28 | template: ` 29 |
    32 | 36 | 37 |

    38 | Blocking?{{ " " }} 39 | {{ isBlocking ? "Yes, click a link or the back button" : "Nope" }} 40 |

    41 | 42 |

    43 | 48 |

    49 | 50 |

    51 | 52 |

    53 | 54 | ` 55 | } 56 | 57 | const App = { 58 | data: () => ({ n: 0 }), 59 | components: { 60 | Route, 61 | RouterLink, 62 | FormExample 63 | }, 64 | template: ` 65 |
    66 |

    Preventing Transitions

    67 |
    68 |
      69 |
    • 70 | Form 71 |
    • 72 |
    • 73 | One 74 |
    • 75 |
    • 76 | Two 77 |
    • 78 |
    79 | 80 | 81 | 82 | 83 |

    One

    84 |
    85 | 86 |

    Two

    87 |
    88 |
    89 |
    90 | `, 91 | 92 | methods: { 93 | // 94 | } 95 | } 96 | 97 | new Vue({ 98 | components: { 99 | App, 100 | Router 101 | }, 102 | data() { 103 | const p = '/preventing-transitions'; 104 | const basename = location.pathname.split(p)[0] + p + '/'; 105 | return { 106 | basename 107 | } 108 | }, 109 | template: ` 110 | 111 | 112 | 113 | ` 114 | }).$mount('#app') 115 | -------------------------------------------------------------------------------- /examples/preventing-transitions/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/recursive-paths/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, Redirect, MatchFirst } from 'vue-router-lite' 3 | 4 | const PEEPS = [ 5 | { id: 0, name: "Michelle", friends: [1, 2, 3] }, 6 | { id: 1, name: "Sean", friends: [0, 3] }, 7 | { id: 2, name: "Kim", friends: [0, 1, 3] }, 8 | { id: 3, name: "David", friends: [1, 2] } 9 | ]; 10 | 11 | function find(id) { 12 | return PEEPS.find(p => p.id == id); 13 | } 14 | 15 | const Person = { 16 | name: 'Person', 17 | components: { 18 | RouterLink, 19 | Route 20 | }, 21 | props: { 22 | match: Object 23 | }, 24 | computed: { 25 | person() { 26 | return find(this.match.params.id); 27 | } 28 | }, 29 | methods: { 30 | find(id) { 31 | return find(id); 32 | } 33 | }, 34 | template: ` 35 |
    36 |

    37 | {{ person.name }} 38 | ’s Friends 39 |

    40 |
      41 |
    • 42 | {{ find(id).name }} 43 |
    • 44 |
    45 | 46 | 47 | 48 |
    49 | ` 50 | } 51 | 52 | const App = { 53 | data: () => ({ n: 0 }), 54 | components: { 55 | Route, 56 | RouterLink, 57 | Person 58 | }, 59 | template: ` 60 |
    61 |

    No Match (404)

    62 | 63 |
    64 | `, 65 | 66 | methods: { 67 | // 68 | } 69 | } 70 | 71 | new Vue({ 72 | components: { 73 | App, 74 | Router 75 | }, 76 | data() { 77 | const p = '/recursive-paths'; 78 | const basename = location.pathname.split(p)[0] + p + '/'; 79 | return { 80 | basename 81 | } 82 | }, 83 | template: ` 84 | 85 | 86 | 87 | ` 88 | }).$mount('#app') 89 | -------------------------------------------------------------------------------- /examples/recursive-paths/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/route-config/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | // wrap and use this everywhere instead, then when 5 | // sub routes are added to any route it'll work 6 | const RouteWithSubRoutes = { 7 | components: { 8 | Route 9 | }, 10 | props: { 11 | route: Object 12 | }, 13 | computed: { 14 | routeConfig() { 15 | const { path, component, routes, otherProps } = this.route; 16 | return { path, component, routes, otherProps }; 17 | } 18 | }, 19 | methods: { 20 | mergeObject(propsA, propsB) { 21 | return { 22 | ...propsA, 23 | ...propsB 24 | }; 25 | } 26 | }, 27 | template: ` 28 | 29 | 34 | 35 | ` 36 | } 37 | 38 | const Sandwiches = { 39 | template: ` 40 |

    Sandwiches

    41 | ` 42 | } 43 | 44 | const Bus = { 45 | template: ` 46 |

    Bus

    47 | ` 48 | } 49 | 50 | const Cart = { 51 | template: ` 52 |

    Cart

    53 | ` 54 | } 55 | 56 | const Tacos = { 57 | components: { 58 | RouterLink, 59 | Route, 60 | RouteWithSubRoutes 61 | }, 62 | props: { 63 | routes: Array, 64 | default: () => [] 65 | }, 66 | template: ` 67 |
    68 |

    Tacos

    69 |
      70 |
    • 71 | Bus 72 |
    • 73 |
    • 74 | Cart 75 |
    • 76 |
    77 | 78 | 83 |
    84 | ` 85 | } 86 | 87 | const routes = [ 88 | { 89 | path: "/sandwiches", 90 | component: Sandwiches 91 | }, 92 | { 93 | path: "/tacos", 94 | component: Tacos, 95 | routes: [ 96 | { 97 | path: "/tacos/bus", 98 | component: Bus 99 | }, 100 | { 101 | path: "/tacos/cart", 102 | component: Cart 103 | } 104 | ] 105 | } 106 | ]; 107 | 108 | const App = { 109 | data: () => { 110 | return { 111 | routes 112 | } 113 | }, 114 | components: { 115 | Route, 116 | RouterLink, 117 | RouteWithSubRoutes 118 | }, 119 | template: ` 120 |
    121 |

    Route Config

    122 |
    123 |
      124 |
    • 125 | Tacos 126 |
    • 127 |
    • 128 | Sandwiches 129 |
    • 130 |
    131 | 132 | 133 | 138 |
    139 |
    140 | `, 141 | 142 | methods: { 143 | // 144 | } 145 | } 146 | 147 | new Vue({ 148 | components: { 149 | App, 150 | Router 151 | }, 152 | data() { 153 | const p = '/route-config'; 154 | const basename = location.pathname.split(p)[0] + p + '/'; 155 | return { 156 | basename 157 | } 158 | }, 159 | template: ` 160 | 161 | 162 | 163 | ` 164 | }).$mount('#app') 165 | -------------------------------------------------------------------------------- /examples/route-config/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const rewrite = require('express-urlrewrite') 3 | const webpack = require('webpack') 4 | const webpackDevMiddleware = require('webpack-dev-middleware') 5 | const WebpackConfig = require('./webpack.config') 6 | const publicPath = process.env.PUBLIC_PATH || '/' 7 | 8 | const app = express() 9 | 10 | const fs = require('fs') 11 | const path = require('path') 12 | 13 | fs.readdirSync(__dirname).forEach(file => { 14 | if (fs.statSync(path.join(__dirname, file)).isDirectory()) { 15 | app.use(rewrite('/' + file + '/*', '/' + file + '/index.html')) 16 | } 17 | }) 18 | 19 | app.use( 20 | webpackDevMiddleware(webpack(WebpackConfig), { 21 | publicPath, 22 | stats: { 23 | colors: true, 24 | chunks: false 25 | } 26 | }) 27 | ) 28 | 29 | app.use(express.static(__dirname)) 30 | 31 | const port = process.env.PORT || 8080 32 | module.exports = app.listen(port, () => { 33 | console.log(`Server listening on http://localhost:${port}, Ctrl+C to stop`) 34 | }) 35 | -------------------------------------------------------------------------------- /examples/sidebar/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | const routes = [ 5 | { 6 | path: "/", 7 | exact: true, 8 | sidebar: { 9 | template: `
    home!
    ` 10 | }, 11 | main: { 12 | template: `
    home!
    ` 13 | } 14 | }, 15 | { 16 | path: "/bubblegum", 17 | sidebar: { 18 | template: `
    bubblegum!
    ` 19 | }, 20 | main: { 21 | template: `
    bubblegum!
    ` 22 | } 23 | }, 24 | { 25 | path: "/shoelaces", 26 | sidebar: { 27 | template: `
    shoelaces!
    ` 28 | }, 29 | main: { 30 | template: `
    shoelaces!
    ` 31 | } 32 | } 33 | ]; 34 | 35 | const App = { 36 | data: () => { 37 | return { 38 | routes 39 | } 40 | }, 41 | components: { 42 | Route, 43 | RouterLink 44 | }, 45 | template: ` 46 |
    47 |

    Sidebar

    48 |
    49 |
    56 |
      57 |
    • 58 | Home 59 |
    • 60 |
    • 61 | Bubblegum 62 |
    • 63 |
    • 64 | Shoelaces 65 |
    • 66 |
    67 | 68 | 75 | 76 | 77 |
    78 | 79 |
    80 | 87 | 88 | 89 |
    90 |
    91 |
    92 | `, 93 | 94 | methods: { 95 | // 96 | } 97 | } 98 | 99 | new Vue({ 100 | components: { 101 | App, 102 | Router 103 | }, 104 | data() { 105 | const p = '/sidebar'; 106 | const basename = location.pathname.split(p)[0] + p + '/'; 107 | return { 108 | basename 109 | } 110 | }, 111 | template: ` 112 | 113 | 114 | 115 | ` 116 | }).$mount('#app') 117 | -------------------------------------------------------------------------------- /examples/sidebar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/static-router/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { StaticRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | 4 | const Home = { 5 | props: { 6 | history: Object 7 | }, 8 | template: ` 9 |
    10 |

    Home

    11 |
    Status Code: {{ history.context.statusCode }}
    12 |
    13 | ` 14 | } 15 | 16 | const About = { 17 | template: ` 18 |
    19 |

    About

    20 |
    21 | ` 22 | } 23 | 24 | const SetStatusCode = { 25 | functional: true, 26 | props: { 27 | code: String, 28 | history: Object 29 | }, 30 | render(h, context) { 31 | const { history, code } = context.props; 32 | history.context.statusCode = code; 33 | return null; 34 | } 35 | } 36 | 37 | const Topic = { 38 | props: { 39 | topicId: { 40 | type: String, 41 | required: true 42 | } 43 | }, 44 | template: ` 45 |
    46 |

    {{ topicId }}

    47 |
    48 | ` 49 | } 50 | 51 | const Topics = { 52 | components: { 53 | RouterLink, 54 | Topic, 55 | Route 56 | }, 57 | props: { 58 | match: { 59 | type: Object, 60 | required: true 61 | } 62 | }, 63 | mounted() { 64 | // console.log(this.match) 65 | }, 66 | template: ` 67 |
    68 |

    Topics

    69 |
      70 |
    • 71 | 72 | Rendering: {{href}} 73 | 74 |
    • 75 |
    • 76 | 77 | Components: {{href}} 78 | 79 |
    • 80 |
    • 81 | 82 | Props v. State: {{href}} 83 | 84 |
    • 85 |
    86 | 87 | 88 | 89 | 90 | 94 |

    Please select a topic.

    95 |
    96 |
    97 | ` 98 | } 99 | 100 | const App = { 101 | data: () => ({ n: 0 }), 102 | components: { 103 | Route, 104 | RouterLink, 105 | Home, 106 | About, 107 | Topics, 108 | SetStatusCode 109 | }, 110 | template: ` 111 |
    112 |

    StaticRouter

    113 |
    StaticRouter can not click to navigate, copy the href to address bar.
    114 |
      115 |
    • 116 | 117 | Home: {{href}} 118 | 119 |
    • 120 |
    • 121 | 122 | About: {{href}} 123 | 124 |
    • 125 |
    • 126 | 127 | Topics: {{href}} 128 | 129 |
    • 130 |
    131 | 132 |
    133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 |
    150 | `, 151 | 152 | methods: { 153 | // 154 | } 155 | } 156 | 157 | new Vue({ 158 | components: { 159 | App, 160 | Router 161 | }, 162 | data() { 163 | const p = '/static-router'; 164 | const basename = location.pathname.split(p)[0] + p + '/'; 165 | return { 166 | basename, 167 | context: { 168 | statusCode: 200 169 | }, 170 | location: { 171 | pathname: window.location.pathname 172 | } 173 | } 174 | }, 175 | template: ` 176 | 177 | 178 | 179 | ` 180 | }).$mount('#app') 181 | -------------------------------------------------------------------------------- /examples/static-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/transitions/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink, RouteSwitch } from 'vue-router-lite' 3 | 4 | const Home = { 5 | template: ` 6 |
    7 |

    Home

    8 |

    hello

    9 |
    10 | ` 11 | } 12 | 13 | const Default = { template: '
    default
    ' } 14 | const Foo = { template: '
    foo
    ' } 15 | const Bar = { template: '
    bar
    ' } 16 | 17 | const Parent = { 18 | props: { 19 | history: Object, 20 | match: Object, 21 | location: Object 22 | }, 23 | components: { 24 | RouterLink, 25 | Route, 26 | RouteSwitch, 27 | Default, 28 | Foo, 29 | Bar 30 | }, 31 | data () { 32 | return { 33 | transitionName: 'slide-left' 34 | } 35 | }, 36 | watch: { 37 | location(val, oldVal) { 38 | console.log('update location') 39 | const toDepth = val.pathname.split('/').length 40 | const fromDepth = oldVal.pathname.split('/').length 41 | this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' 42 | }, 43 | transitionName() { 44 | console.log('update transitionName') 45 | } 46 | }, 47 | beforeUpdate() { 48 | console.log('update parent') 49 | }, 50 | template: ` 51 |
    52 |

    Parent

    53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
    67 | ` 68 | } 69 | 70 | const App = { 71 | components: { 72 | RouterLink, 73 | Route, 74 | RouteSwitch, 75 | Home, 76 | Parent 77 | }, 78 | props: { 79 | history: Object 80 | }, 81 | template: ` 82 |
    83 |

    Transitions

    84 |
      85 |
    • /
    • 86 |
    • /parent
    • 87 |
    • /parent/foo
    • 88 |
    • /parent/bar
    • 89 |
    90 |
    91 | 92 |
    93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
    104 | ` 105 | }; 106 | 107 | new Vue({ 108 | components: { 109 | Router, 110 | App 111 | }, 112 | data() { 113 | const p = '/transitions'; 114 | const basename = location.pathname.split(p)[0] + p + '/'; 115 | return { 116 | basename 117 | } 118 | }, 119 | template: ` 120 | 121 | 122 | 123 | ` 124 | }).$mount('#app') 125 | -------------------------------------------------------------------------------- /examples/transitions/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 34 | 35 | 36 | 37 | ← Examples index 38 |
    39 | 40 | <% for (var js in htmlWebpackPlugin.files.js) { %> 41 | 42 | <% } %> 43 | 44 | -------------------------------------------------------------------------------- /examples/url-parameters/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { BrowserRouter as Router, Route, RouterLink } from 'vue-router-lite' 3 | import { basename } from 'path'; 4 | 5 | const Child = { 6 | props: { 7 | id: String 8 | }, 9 | template: ` 10 |
    11 |

    ID: {{ id }}

    12 |
    13 | ` 14 | } 15 | 16 | const ChildRegex = { 17 | props: { 18 | id: String 19 | }, 20 | template: ` 21 |
    22 |

    Only yahoo/netflix are matched: {{ id }}

    23 |
    24 | ` 25 | } 26 | 27 | const App = { 28 | data: () => ({ n: 0 }), 29 | components: { 30 | Route, 31 | RouterLink, 32 | Child, 33 | ChildRegex 34 | }, 35 | template: ` 36 |
    37 |

    URL Parameters

    38 |
      39 |
    • 40 | Netflix 41 |
    • 42 |
    • 43 | Zillow Group 44 |
    • 45 |
    • 46 | Yahoo 47 |
    • 48 |
    • 49 | Modus Create 50 |
    • 51 |
    52 | 53 |
    54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 | `, 64 | 65 | methods: { 66 | // 67 | } 68 | } 69 | 70 | new Vue({ 71 | components: { 72 | App, 73 | Router 74 | }, 75 | data() { 76 | const p = '/url-parameters'; 77 | const basename = location.pathname.split(p)[0] + p + '/'; 78 | return { 79 | basename 80 | } 81 | }, 82 | template: ` 83 | 84 | 85 | 86 | ` 87 | }).$mount('#app') 88 | -------------------------------------------------------------------------------- /examples/url-parameters/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vue Router Lite Examples 7 | 8 | <% for (var css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | 14 | ← Examples index 15 |
    16 | 17 | <% for (var js in htmlWebpackPlugin.files.js) { %> 18 | 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /examples/webpack.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const VuePlugin = require('vue-loader/lib/plugin') 4 | const HtmlWebpackPlugin = require('html-webpack-plugin') 5 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 6 | 7 | const isProduction = process.env.NODE_ENV === 'production' 8 | const publicPath = process.env.PUBLIC_PATH || '/' 9 | const htmlPlugins = [ 10 | new HtmlWebpackPlugin({ 11 | filename: 'index.html', 12 | template: path.join(__dirname, 'index.html'), 13 | inject: false, 14 | publicPath, 15 | chunks: ['global.css'] 16 | }) 17 | ] 18 | const entry = fs.readdirSync(__dirname).reduce((entries, dir) => { 19 | const fullDir = path.join(__dirname, dir) 20 | const entry = path.join(fullDir, 'app.js') 21 | const entryName = path.join('js', dir); 22 | if (fs.statSync(fullDir).isDirectory() && fs.existsSync(entry)) { 23 | entries[entryName] = entry; 24 | const filename = path.join(dir, 'index.html') 25 | const template = path.join(fullDir, 'index.html') 26 | htmlPlugins.push(new HtmlWebpackPlugin({ 27 | filename, 28 | template, 29 | inject: false, 30 | publicPath, 31 | chunks: ['global.css', entryName] 32 | })) 33 | } 34 | 35 | return entries 36 | }, {}) 37 | 38 | entry['global.css'] = path.join(__dirname, 'global.css') 39 | 40 | module.exports = { 41 | // Expose __dirname to allow automatically setting basename. 42 | context: __dirname, 43 | node: { 44 | __dirname: true 45 | }, 46 | 47 | mode: isProduction ? 'production' : 'development', 48 | 49 | entry, 50 | 51 | output: { 52 | path: path.join(__dirname, '__build__'), 53 | filename: '[name].js', 54 | chunkFilename: '[name].chunk.js', 55 | publicPath 56 | }, 57 | 58 | module: { 59 | rules: [ 60 | { 61 | test: /\.html$/, 62 | use: [ 63 | { 64 | loader: 'ejs-loader' 65 | }, 66 | { 67 | loader: "extract-loader", 68 | }, 69 | { 70 | loader: 'html-loader', 71 | options: { 72 | minimize: false 73 | } 74 | } 75 | ] 76 | }, 77 | { 78 | test: /\.js$/, 79 | exclude: /node_modules/, 80 | use: { 81 | loader: 'babel-loader', 82 | options: { 83 | babelrc: false, 84 | presets: ['@babel/preset-env'], 85 | plugins: [ 86 | '@babel/plugin-syntax-dynamic-import', 87 | '@babel/plugin-proposal-object-rest-spread' 88 | ] 89 | } 90 | } 91 | }, 92 | { 93 | test: /\.vue$/, 94 | use: 'vue-loader' 95 | }, 96 | { 97 | test: /\.css$/, 98 | use: [ 99 | { 100 | loader: MiniCssExtractPlugin.loader, 101 | options: { 102 | publicPath, 103 | hmr: !isProduction 104 | }, 105 | }, 106 | 'css-loader' 107 | ] 108 | } 109 | ] 110 | }, 111 | 112 | resolve: { 113 | alias: { 114 | vue: 'vue/dist/vue.esm.js', 115 | 'vue-router-lite': path.join(__dirname, '..', 'dist/vue-router-lite.module.js') 116 | } 117 | }, 118 | 119 | optimization: { 120 | runtimeChunk: { 121 | name: 'runtime' 122 | }, 123 | splitChunks: { 124 | cacheGroups: { 125 | 'shared': { 126 | name: 'js/shared', 127 | test: /[\\/]node_modules[\\/]/, 128 | minChunks: 2 129 | } 130 | } 131 | } 132 | }, 133 | 134 | plugins: [ 135 | new VuePlugin(), 136 | new MiniCssExtractPlugin({ 137 | filename: 'css/[name].css', 138 | chunkFilename: 'css/[name].chunk.css', 139 | }), 140 | ] 141 | .concat(htmlPlugins) 142 | } 143 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | module.exports = { 5 | // All imported modules in your tests should be mocked automatically 6 | // automock: false, 7 | 8 | // Stop running tests after `n` failures 9 | // bail: 0, 10 | 11 | // Respect "browser" field in package.json when resolving modules 12 | // browser: false, 13 | 14 | // The directory where Jest should store its cached dependency information 15 | // cacheDirectory: "/private/var/folders/qr/z0cq6m_12lq7kd6_nh6jl13w0000gn/T/jest_dx", 16 | 17 | // Automatically clear mock calls and instances between every test 18 | clearMocks: true, 19 | 20 | // Indicates whether the coverage information should be collected while executing the test 21 | collectCoverage: true, 22 | 23 | // An array of glob patterns indicating a set of files for which coverage information should be collected 24 | collectCoverageFrom: [ 25 | "src/**.{js,vue}", 26 | "!**/node_modules/**" 27 | ], 28 | 29 | // The directory where Jest should output its coverage files 30 | coverageDirectory: "coverage", 31 | 32 | // An array of regexp pattern strings used to skip coverage collection 33 | // coveragePathIgnorePatterns: [ 34 | // "/node_modules/" 35 | // ], 36 | 37 | // A list of reporter names that Jest uses when writing coverage reports 38 | // coverageReporters: [ 39 | // "json", 40 | // "text", 41 | // "lcov", 42 | // "clover" 43 | // ], 44 | 45 | // An object that configures minimum threshold enforcement for coverage results 46 | // coverageThreshold: null, 47 | 48 | // A path to a custom dependency extractor 49 | // dependencyExtractor: null, 50 | 51 | // Make calling deprecated APIs throw helpful error messages 52 | // errorOnDeprecated: false, 53 | 54 | // Force coverage collection from ignored files using an array of glob patterns 55 | // forceCoverageMatch: [], 56 | 57 | // A path to a module which exports an async function that is triggered once before all test suites 58 | // globalSetup: null, 59 | 60 | // A path to a module which exports an async function that is triggered once after all test suites 61 | // globalTeardown: null, 62 | 63 | // A set of global variables that need to be available in all test environments 64 | // globals: {}, 65 | 66 | // An array of directory names to be searched recursively up from the requiring module's location 67 | // moduleDirectories: [ 68 | // "node_modules" 69 | // ], 70 | 71 | // An array of file extensions your modules use 72 | moduleFileExtensions: [ 73 | "js", 74 | "json", 75 | "jsx", 76 | "ts", 77 | "tsx", 78 | "node", 79 | "vue" 80 | ], 81 | 82 | // A map from regular expressions to module names that allow to stub out resources with a single module 83 | moduleNameMapper: { 84 | "vue-router-lite": "/dist/vue-router-lite.js" 85 | }, 86 | 87 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 88 | // modulePathIgnorePatterns: [], 89 | 90 | // Activates notifications for test results 91 | // notify: false, 92 | 93 | // An enum that specifies notification mode. Requires { notify: true } 94 | // notifyMode: "failure-change", 95 | 96 | // A preset that is used as a base for Jest's configuration 97 | // preset: null, 98 | 99 | // Run tests from one or more projects 100 | // projects: null, 101 | 102 | // Use this configuration option to add custom reporters to Jest 103 | // reporters: undefined, 104 | 105 | // Automatically reset mock state between every test 106 | // resetMocks: false, 107 | 108 | // Reset the module registry before running each individual test 109 | // resetModules: false, 110 | 111 | // A path to a custom resolver 112 | // resolver: null, 113 | 114 | // Automatically restore mock state between every test 115 | // restoreMocks: false, 116 | 117 | // The root directory that Jest should scan for tests and modules within 118 | // rootDir: null, 119 | 120 | // A list of paths to directories that Jest should use to search for files in 121 | // roots: [ 122 | // "" 123 | // ], 124 | 125 | // Allows you to use a custom runner instead of Jest's default test runner 126 | // runner: "jest-runner", 127 | 128 | // The paths to modules that run some code to configure or set up the testing environment before each test 129 | // setupFiles: [], 130 | 131 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 132 | // setupFilesAfterEnv: [], 133 | 134 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 135 | snapshotSerializers: [ 136 | "/node_modules/jest-serializer-vue" 137 | ], 138 | 139 | // The test environment that will be used for testing 140 | testEnvironment: "jest-environment-jsdom-global", 141 | 142 | // Options that will be passed to the testEnvironment 143 | // testEnvironmentOptions: {}, 144 | 145 | // Adds a location field to test results 146 | // testLocationInResults: false, 147 | 148 | // The glob patterns Jest uses to detect test files 149 | // testMatch: [ 150 | // "**/__tests__/**/*.[jt]s?(x)", 151 | // "**/?(*.)+(spec|test).[tj]s?(x)" 152 | // ], 153 | 154 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 155 | // testPathIgnorePatterns: [ 156 | // "/node_modules/" 157 | // ], 158 | 159 | // The regexp pattern or array of patterns that Jest uses to detect test files 160 | testRegex: [ 161 | "/test/.*\\.test\\.js$" 162 | ], 163 | 164 | // This option allows the use of a custom results processor 165 | // testResultsProcessor: null, 166 | 167 | // This option allows use of a custom test runner 168 | // testRunner: "jasmine2", 169 | 170 | // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href 171 | // testURL: "http://localhost", 172 | 173 | // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" 174 | // timers: "real", 175 | 176 | // A map from regular expressions to paths to transformers 177 | "transform": { 178 | "^.+\\.js$": "/node_modules/babel-jest", 179 | ".*\\.(vue)$": "/node_modules/vue-jest" 180 | }, 181 | 182 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 183 | // transformIgnorePatterns: [ 184 | // "/node_modules/" 185 | // ], 186 | 187 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 188 | // unmockedModulePathPatterns: undefined, 189 | 190 | // Indicates whether each individual test should be reported during the run 191 | // verbose: null, 192 | 193 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 194 | // watchPathIgnorePatterns: [], 195 | 196 | // Whether to use watchman for file crawling 197 | // watchman: true, 198 | }; 199 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-router-lite", 3 | "version": "1.3.0", 4 | "description": "> `vue-router-lite` is a component-based router for Vue.js.", 5 | "main": "dist/vue-router-lite.js", 6 | "module": "dist/vue-router-lite.module.js", 7 | "unpkg": "dist/vue-router-lite.umd.js", 8 | "devDependencies": { 9 | "@babel/core": "^7.9.0", 10 | "@babel/plugin-proposal-object-rest-spread": "^7.9.5", 11 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 12 | "@babel/preset-env": "^7.9.5", 13 | "@rollup/plugin-commonjs": "^11.0.2", 14 | "@rollup/plugin-node-resolve": "^7.1.1", 15 | "@rollup/plugin-replace": "^2.3.1", 16 | "@vue/test-utils": "^1.0.0-beta.33", 17 | "babel-core": "^7.0.0-bridge.0", 18 | "babel-eslint": "^10.1.0", 19 | "babel-jest": "^25.3.0", 20 | "babel-loader": "^8.1.0", 21 | "cross-env": "^7.0.2", 22 | "css-loader": "^3.5.2", 23 | "ejs-loader": "^0.3.6", 24 | "eslint": "6.8.0", 25 | "eslint-config-airbnb": "18.1.0", 26 | "eslint-config-airbnb-base": "14.1.0", 27 | "eslint-config-prettier": "6.10.1", 28 | "eslint-import-resolver-alias": "^1.1.2", 29 | "eslint-plugin-babel": "5.3.0", 30 | "eslint-plugin-import": "^2.20.2", 31 | "eslint-plugin-prettier": "3.1.2", 32 | "eslint-plugin-vue": "6.2.2", 33 | "prettier": "2.0.4", 34 | "express": "^4.17.1", 35 | "express-urlrewrite": "^1.2.0", 36 | "extract-loader": "^5.0.1", 37 | "fs-extra": "^9.0.0", 38 | "html-loader": "^1.1.0", 39 | "html-webpack-plugin": "^4.2.0", 40 | "jest": "^25.3.0", 41 | "jest-environment-jsdom": "^25.3.0", 42 | "jest-environment-jsdom-global": "^2.0.2", 43 | "jest-serializer-vue": "^2.0.2", 44 | "mini-css-extract-plugin": "^0.9.0", 45 | "rollup": "^2.6.0", 46 | "rollup-plugin-babel": "^4.4.0", 47 | "rollup-plugin-filesize": "^7.0.0", 48 | "rollup-plugin-terser": "^5.3.0", 49 | "rollup-plugin-vue": "^5.1.6", 50 | "typescript": "^3.8.3", 51 | "vue": "^2.6.11", 52 | "vue-jest": "^3.0.5", 53 | "vue-loader": "^15.9.1", 54 | "vue-template-compiler": "^2.6.11", 55 | "webpack": "^4.42.1", 56 | "webpack-cli": "^3.3.11", 57 | "webpack-dev-middleware": "^3.7.2" 58 | }, 59 | "scripts": { 60 | "build": "node build/build.js", 61 | "examples": "cross-env NODE_ENV=development node examples/server.js", 62 | "examples:build": "cross-env NODE_ENV=production webpack --config examples/webpack.config.js", 63 | "docs": "cd docs && npm run docs", 64 | "docs:build": "cd docs && npm run docs:build", 65 | "test": "jest", 66 | "install-cn": "npm i --chromedriver_cdnurl=https://npm.taobao.org/mirrors/chromedriver" 67 | }, 68 | "repository": { 69 | "type": "git", 70 | "url": "git+https://github.com/ccqgithub/vue-router-lite.git" 71 | }, 72 | "author": "", 73 | "license": "MIT", 74 | "bugs": { 75 | "url": "https://github.com/ccqgithub/vue-router-lite/issues" 76 | }, 77 | "homepage": "https://github.com/ccqgithub/vue-router-lite#readme", 78 | "dependencies": { 79 | "history": "^4.10.1", 80 | "path-to-regexp": "^6.1.0" 81 | }, 82 | "peerDependencies": { 83 | "vue": "^2.6.0" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/component/BrowserRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 56 | -------------------------------------------------------------------------------- /src/component/HashRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 53 | -------------------------------------------------------------------------------- /src/component/MemoryRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 53 | -------------------------------------------------------------------------------- /src/component/Prompt.vue: -------------------------------------------------------------------------------- 1 | 76 | -------------------------------------------------------------------------------- /src/component/Redirect.vue: -------------------------------------------------------------------------------- 1 | 128 | -------------------------------------------------------------------------------- /src/component/Route.vue: -------------------------------------------------------------------------------- 1 | 134 | -------------------------------------------------------------------------------- /src/component/RouteContext.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /src/component/RouteSwitch.vue: -------------------------------------------------------------------------------- 1 | 140 | -------------------------------------------------------------------------------- /src/component/Router.vue: -------------------------------------------------------------------------------- 1 | 84 | -------------------------------------------------------------------------------- /src/component/RouterLink.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 173 | -------------------------------------------------------------------------------- /src/component/StaticRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 48 | -------------------------------------------------------------------------------- /src/component/Tag.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import MemoryRouter from './component/MemoryRouter.vue'; 2 | import HashRouter from './component/HashRouter.vue'; 3 | import BrowserRouter from './component/BrowserRouter.vue'; 4 | import StaticRouter from './component/StaticRouter.vue'; 5 | import Router from './component/Router.vue'; 6 | import RouterLink from './component/RouterLink.vue'; 7 | import Prompt from './component/Prompt.vue'; 8 | import Redirect from './component/Redirect.vue'; 9 | import Route from './component/Route.vue'; 10 | import RouteContext from './component/RouteContext.vue'; 11 | import RouteSwitch from './component/RouteSwitch.vue'; 12 | 13 | import generatePath from './util/generatePath'; 14 | import matchPath from './util/matchPath'; 15 | import createBrowserHistory from './util/createBrowserHistory'; 16 | import createHashHistory from './util/createHashHistory'; 17 | import createMemoryHistory from './util/createMemoryHistory'; 18 | import createStaticHistory from './util/createStaticHistory'; 19 | 20 | export { 21 | MemoryRouter, 22 | HashRouter, 23 | BrowserRouter, 24 | StaticRouter, 25 | Router, 26 | RouterLink, 27 | Prompt, 28 | Redirect, 29 | Route, 30 | RouteContext, 31 | RouteSwitch, 32 | generatePath, 33 | matchPath, 34 | createBrowserHistory, 35 | createHashHistory, 36 | createMemoryHistory, 37 | createStaticHistory 38 | }; 39 | 40 | const install = function install(Vue) { 41 | [ 42 | MemoryRouter, 43 | HashRouter, 44 | BrowserRouter, 45 | StaticRouter, 46 | Router, 47 | RouterLink, 48 | Prompt, 49 | Redirect, 50 | Route, 51 | RouteContext, 52 | RouteSwitch 53 | ].forEach((component) => { 54 | Vue.component(component.name, component); 55 | }); 56 | }; 57 | 58 | /* istanbul ignore if */ 59 | if (typeof window !== 'undefined' && window.Vue) { 60 | install(window.Vue); 61 | } 62 | 63 | export default { 64 | version: '__VERSION__', 65 | install 66 | }; 67 | -------------------------------------------------------------------------------- /src/util/createBrowserHistory.js: -------------------------------------------------------------------------------- 1 | export { createBrowserHistory as default } from 'history'; 2 | -------------------------------------------------------------------------------- /src/util/createHashHistory.js: -------------------------------------------------------------------------------- 1 | export { createHashHistory as default } from 'history'; 2 | -------------------------------------------------------------------------------- /src/util/createMemoryHistory.js: -------------------------------------------------------------------------------- 1 | export { createMemoryHistory as default } from 'history'; 2 | -------------------------------------------------------------------------------- /src/util/createStaticHistory.js: -------------------------------------------------------------------------------- 1 | import { createLocation, createPath } from 'history'; 2 | 3 | const addLeadingSlash = (path) => { 4 | return path.charAt(0) === '/' ? path : `/${path}`; 5 | }; 6 | 7 | const removeTailSlash = (path) => { 8 | return path.replace(/\/+$/, ''); 9 | }; 10 | 11 | const addBasename = (basename, location) => { 12 | if (!basename) return location; 13 | 14 | return { 15 | ...location, 16 | pathname: 17 | removeTailSlash(addLeadingSlash(basename)) + 18 | addLeadingSlash(location.pathname) 19 | }; 20 | }; 21 | 22 | const stripBasename = (basename, location) => { 23 | if (!basename) return location; 24 | 25 | const base = addLeadingSlash(basename); 26 | 27 | if (location.pathname.indexOf(base) !== 0) return location; 28 | 29 | return { 30 | ...location, 31 | pathname: addLeadingSlash(location.pathname.substr(base.length)) 32 | }; 33 | }; 34 | 35 | const createURL = (location) => 36 | typeof location === 'string' ? location : createPath(location); 37 | 38 | const staticHandler = (methodName) => () => { 39 | throw new Error(`You cannot ${methodName} with `); 40 | }; 41 | 42 | const noop = () => {}; 43 | 44 | function createStaticHistory({ basename = '', context = {}, location = '/' }) { 45 | const history = { 46 | isStatic: true, 47 | context, 48 | action: 'POP', 49 | location: stripBasename(basename, createLocation(location)), 50 | go: staticHandler('go'), 51 | goBack: staticHandler('goBack'), 52 | goForward: staticHandler('goForward'), 53 | createHref: (loc) => { 54 | return addLeadingSlash(removeTailSlash(basename) + createURL(loc)); 55 | }, 56 | push: (loc) => { 57 | context.action = 'PUSH'; 58 | context.location = addBasename(basename, createLocation(loc)); 59 | context.url = createURL(context.location); 60 | }, 61 | replace: (loc) => { 62 | context.action = 'REPLACE'; 63 | context.location = addBasename(basename, createLocation(loc)); 64 | context.url = createURL(context.location); 65 | }, 66 | listen: () => noop, 67 | block: () => noop 68 | }; 69 | 70 | return history; 71 | } 72 | 73 | export default createStaticHistory; 74 | -------------------------------------------------------------------------------- /src/util/generatePath.js: -------------------------------------------------------------------------------- 1 | /** 2 | * reference from: 3 | * https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/generatePath.js 4 | */ 5 | 6 | import { compile } from 'path-to-regexp'; 7 | 8 | const cache = {}; 9 | const cacheLimit = 10000; 10 | let cacheCount = 0; 11 | 12 | function compilePath(path) { 13 | if (cache[path]) return cache[path]; 14 | 15 | const generator = compile(path); 16 | 17 | if (cacheCount < cacheLimit) { 18 | cache[path] = generator; 19 | cacheCount++; 20 | } 21 | 22 | return generator; 23 | } 24 | 25 | /** 26 | * generating a URL pathname from a path and parameters. 27 | */ 28 | function generatePath(path = '/', params = {}, options = {}) { 29 | return path === '/' ? path : compilePath(path)(params, options); 30 | } 31 | 32 | export default generatePath; 33 | -------------------------------------------------------------------------------- /src/util/matchPath.js: -------------------------------------------------------------------------------- 1 | /** 2 | * reference from: 3 | * https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/matchPath.js 4 | */ 5 | 6 | import { pathToRegexp } from 'path-to-regexp'; 7 | 8 | const cache = {}; 9 | const cacheLimit = 10000; 10 | let cacheCount = 0; 11 | 12 | function compilePath(path, options) { 13 | const cacheKey = `${options.end}-${options.strict}-${options.sensitive}`; 14 | const pathCache = cache[cacheKey] || (cache[cacheKey] = {}); 15 | 16 | if (pathCache[path]) return pathCache[path]; 17 | 18 | const keys = []; 19 | const regexp = pathToRegexp(path, keys, options); 20 | const result = { regexp, keys }; 21 | 22 | if (cacheCount < cacheLimit) { 23 | pathCache[path] = result; 24 | cacheCount++; 25 | } 26 | 27 | return result; 28 | } 29 | 30 | /** 31 | * matching a URL pathname to a path. 32 | * pathname: current locations's pathname 33 | */ 34 | function matchPath(pathname, options = {}) { 35 | if (typeof options === 'string') options = { path: options }; 36 | 37 | const { path: p, exact = false, strict = false, sensitive = true } = options; 38 | 39 | const paths = [].concat(p); 40 | 41 | return paths.reduce((matched, path) => { 42 | if (matched) return matched; 43 | const { regexp, keys } = compilePath(path, { 44 | end: exact, 45 | strict, 46 | sensitive 47 | }); 48 | const match = regexp.exec(pathname); 49 | 50 | if (!match) return null; 51 | 52 | const [url, ...values] = match; 53 | const isExact = pathname === url; 54 | 55 | if (exact && !isExact) return null; 56 | 57 | return { 58 | path, // the path used to match 59 | url: path === '/' && url === '' ? '/' : url, // the matched portion of the URL 60 | isExact, // whether or not we matched exactly 61 | params: keys.reduce((memo, key, index) => { 62 | memo[key.name] = values[index]; 63 | return memo; 64 | }, {}) 65 | }; 66 | }, null); 67 | } 68 | 69 | export default matchPath; 70 | -------------------------------------------------------------------------------- /src/util/symbol.js: -------------------------------------------------------------------------------- 1 | export function getSymbol(str) { 2 | if (typeof Symbol === 'function') { 3 | return Symbol(str); 4 | } 5 | return `vue-router-lite-symbol-${str}`; 6 | } 7 | 8 | export const route = getSymbol('route'); 9 | export const router = getSymbol('router'); 10 | -------------------------------------------------------------------------------- /src/util/utils.js: -------------------------------------------------------------------------------- 1 | import { createLocation } from 'history'; 2 | 3 | export function assert(condition, message) { 4 | if (!condition) { 5 | throw new Error(`[vue-router-lite] ${message}`); 6 | } 7 | } 8 | 9 | export function warn(condition, message) { 10 | if (process.env.NODE_ENV !== 'production' && !condition) { 11 | if (typeof console !== 'undefined') 12 | console.warn(`[vue-router-lite] ${message}`); 13 | } 14 | } 15 | 16 | export function isError(err) { 17 | return Object.prototype.toString.call(err).indexOf('Error') > -1; 18 | } 19 | 20 | // copyJson 21 | export function copyJson(data) { 22 | return JSON.parse(JSON.stringify(data)); 23 | } 24 | 25 | // 26 | export const resolveToLocation = (to, currentLocation) => 27 | typeof to === 'function' ? to(currentLocation) : to; 28 | 29 | // 30 | export const normalizeToLocation = (to, currentLocation) => { 31 | return typeof to === 'string' 32 | ? createLocation(to, null, null, currentLocation) 33 | : to; 34 | }; 35 | 36 | export const guardEvent = (e) => { 37 | // don't redirect with control keys 38 | if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return; 39 | // don't redirect when preventDefault called 40 | if (e.defaultPrevented) return; 41 | // don't redirect on right click 42 | if (e.button !== undefined && e.button !== 0) return; 43 | // don't redirect if `target="_blank"` 44 | if (e.currentTarget && e.currentTarget.getAttribute) { 45 | const target = e.currentTarget.getAttribute('target'); 46 | if (/\b_blank\b/i.test(target)) return; 47 | } 48 | // this may be a Weex event which doesn't have this method 49 | if (e.preventDefault) { 50 | e.preventDefault(); 51 | } 52 | return true; 53 | }; 54 | 55 | export function isAsyncPlaceholder(node) { 56 | return node.isComment && node.asyncFactory; 57 | } 58 | 59 | export function isNotTextNode(c) { 60 | return c.tag || isAsyncPlaceholder(c); 61 | } 62 | 63 | export function getBooleanProps(val, defaultVal = false) { 64 | if (typeof val === 'undefined') return defaultVal; 65 | return val !== 'false'; 66 | } 67 | -------------------------------------------------------------------------------- /test/specs/apps/BrowserRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /test/specs/apps/HashRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /test/specs/apps/MemoryRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /test/specs/apps/RouterApp.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 45 | -------------------------------------------------------------------------------- /test/specs/apps/StaticRouter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /test/specs/apps/components/About.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /test/specs/apps/components/Home.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /test/specs/apps/components/Topic.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /test/specs/apps/components/Topics.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 51 | -------------------------------------------------------------------------------- /test/specs/router.test.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import BrowserRouter from './apps/BrowserRouter.vue'; 3 | import HashRouter from './apps/HashRouter.vue'; 4 | import MemoryRouter from './apps/MemoryRouter.vue'; 5 | import StaticRouter from './apps/StaticRouter.vue'; 6 | 7 | describe('browser router', () => { 8 | test('home', () => { 9 | jsdom.reconfigure({ 10 | url: "http://localhost/test/" 11 | }); 12 | const wrapper = mount(BrowserRouter, { 13 | propsData: { 14 | basename: '/test/' 15 | } 16 | }); 17 | const pages = wrapper.findAll('.mod'); 18 | expect(pages.at(0).is('.home')).toBe(true); 19 | }); 20 | 21 | test('tpoic: props-v-state', () => { 22 | jsdom.reconfigure({ 23 | url: "http://localhost/test/topics/props-v-state" 24 | }); 25 | const wrapper = mount(BrowserRouter, { 26 | propsData: { 27 | basename: '/test/' 28 | } 29 | }); 30 | const h3 = wrapper.find('.mod.topic').find('h3'); 31 | expect(h3.text()).toBe('props-v-state'); 32 | }); 33 | }); 34 | 35 | describe('hash router', () => { 36 | test('home', () => { 37 | jsdom.reconfigure({ 38 | url: "http://localhost/#/" 39 | }); 40 | const wrapper = mount(HashRouter, { 41 | propsData: { 42 | basename: '/' 43 | } 44 | }); 45 | const pages = wrapper.findAll('.mod'); 46 | expect(pages.at(0).is('.home')).toBe(true); 47 | }); 48 | 49 | test('tpoic: props-v-state', () => { 50 | jsdom.reconfigure({ 51 | url: "http://localhost/#/topics/props-v-state" 52 | }); 53 | const wrapper = mount(HashRouter, { 54 | propsData: { 55 | basename: '/' 56 | } 57 | }); 58 | const h3 = wrapper.find('.mod.topic').find('h3'); 59 | expect(h3.text()).toBe('props-v-state'); 60 | }); 61 | }); 62 | 63 | describe('memory router', () => { 64 | test('home', () => { 65 | const wrapper = mount(MemoryRouter, { 66 | propsData: { 67 | initialEntries: ['/'] 68 | } 69 | }); 70 | const pages = wrapper.findAll('.mod'); 71 | // console.log(pages.at(0).html()) 72 | expect(pages.at(0).is('.home')).toBe(true); 73 | }); 74 | 75 | test('tpoic: props-v-state', () => { 76 | const wrapper = mount(MemoryRouter, { 77 | propsData: { 78 | initialEntries: ['/topics/props-v-state'] 79 | } 80 | }); 81 | const h3 = wrapper.find('.mod.topic').find('h3'); 82 | expect(h3.text()).toBe('props-v-state'); 83 | }); 84 | }); 85 | 86 | describe('static router', () => { 87 | test('home', () => { 88 | const wrapper = mount(StaticRouter, { 89 | propsData: { 90 | basename: '/test/', 91 | location: '/' 92 | } 93 | }); 94 | const pages = wrapper.findAll('.mod'); 95 | expect(pages.at(0).is('.home')).toBe(true); 96 | }); 97 | 98 | test('tpoic: props-v-state', () => { 99 | const wrapper = mount(StaticRouter, { 100 | propsData: { 101 | basename: '/test/', 102 | location: '/topics/props-v-state' 103 | } 104 | }); 105 | const h3 = wrapper.find('.mod.topic').find('h3'); 106 | expect(h3.text()).toBe('props-v-state'); 107 | }); 108 | }); --------------------------------------------------------------------------------