├── .babelrc ├── rollup.config.js ├── package.json ├── LICENSE ├── .gitignore ├── src ├── index.js └── querystring.js ├── README.md └── dist └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }] 4 | ] 5 | } -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | 3 | export default { 4 | input: 'src/index.js', 5 | output: { 6 | file: 'dist/index.js', 7 | format: 'es', 8 | }, 9 | external: ['querystring'], 10 | plugins: [babel()], 11 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mpvue-router-patch", 3 | "version": "2.0.0", 4 | "description": "在 mpvue 中使用 vue-router 兼容的路由写法", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "build": "rollup -c", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "files": [ 11 | "dist", 12 | "src" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/F-loat/mpvue-router-patch.git" 17 | }, 18 | "keywords": [ 19 | "mpvue", 20 | "router", 21 | "vue-router" 22 | ], 23 | "author": "F-loat ", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/F-loat/mpvue-router-patch/issues" 27 | }, 28 | "homepage": "https://github.com/F-loat/mpvue-router-patch#readme", 29 | "devDependencies": { 30 | "babel-core": "^6.26.3", 31 | "babel-preset-env": "^1.6.1", 32 | "rollup": "^0.58.2", 33 | "rollup-plugin-babel": "^3.0.4" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 柴茂源 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # idea 61 | .idea/* 62 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { stringify } from './querystring' 2 | 3 | function parseUrl(location) { 4 | if (typeof location === 'string') return location 5 | 6 | const { path, query } = location 7 | const queryStr = stringify(query) 8 | 9 | if (!queryStr) { 10 | return path 11 | } 12 | 13 | return `${path}?${queryStr}` 14 | } 15 | 16 | function parseRoute($mp) { 17 | const _$mp = $mp || {} 18 | const path = _$mp.page && _$mp.page.route 19 | return { 20 | path: `/${path}`, 21 | params: {}, 22 | query: _$mp.query, 23 | hash: '', 24 | fullPath: parseUrl({ 25 | path: `/${path}`, 26 | query: _$mp.query 27 | }), 28 | name: path && path.replace(/\/(\w)/g, ($0, $1) => $1.toUpperCase()) 29 | } 30 | } 31 | 32 | function push(location, complete, fail, success) { 33 | const url = parseUrl(location) 34 | const params = { url, complete, fail, success } 35 | 36 | if (location.isTab) { 37 | mpvue.switchTab(params) 38 | return 39 | } 40 | if (location.reLaunch) { 41 | mpvue.reLaunch(params) 42 | return 43 | } 44 | mpvue.navigateTo(params) 45 | } 46 | 47 | function replace(location, complete, fail, success) { 48 | const url = parseUrl(location) 49 | mpvue.redirectTo({ url, complete, fail, success }) 50 | } 51 | 52 | function go(delta) { 53 | mpvue.navigateBack({ delta }) 54 | } 55 | 56 | function back() { 57 | mpvue.navigateBack() 58 | } 59 | 60 | export let _Vue 61 | 62 | export default { 63 | install(Vue) { 64 | if (this.installed && _Vue === Vue) return 65 | this.installed = true 66 | 67 | _Vue = Vue 68 | 69 | const _router = { 70 | mode: 'history', 71 | push, 72 | replace, 73 | go, 74 | back 75 | } 76 | 77 | Vue.mixin({ 78 | onLoad() { 79 | const { $mp } = this.$root 80 | this._route = parseRoute($mp) 81 | }, 82 | onShow() { 83 | _router.app = this 84 | _router.currentRoute = this._route 85 | } 86 | }) 87 | 88 | Object.defineProperty(Vue.prototype, '$router', { 89 | get() { return _router } 90 | }) 91 | 92 | Object.defineProperty(Vue.prototype, '$route', { 93 | get() { return this._route } 94 | }) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/querystring.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | var stringifyPrimitive = function(v) { 23 | switch (typeof v) { 24 | case 'string': 25 | return v 26 | 27 | case 'boolean': 28 | return v ? 'true' : 'false' 29 | 30 | case 'number': 31 | return isFinite(v) ? v : '' 32 | 33 | default: 34 | return '' 35 | } 36 | } 37 | 38 | function stringify (obj, sep, eq, name) { 39 | sep = sep || '&' 40 | eq = eq || '=' 41 | if (obj === null) { 42 | obj = undefined 43 | } 44 | 45 | if (typeof obj === 'object') { 46 | return Object.keys(obj).map(function(k) { 47 | var ks = stringifyPrimitive(k) + eq 48 | if (Array.isArray(obj[k])) { 49 | return obj[k].map(function(v) { 50 | return ks + stringifyPrimitive(v) 51 | }).join(sep) 52 | } else { 53 | return ks + stringifyPrimitive(obj[k]) 54 | } 55 | }).filter(Boolean).join(sep) 56 | 57 | } 58 | 59 | if (!name) return '' 60 | return stringifyPrimitive(name) + eq + stringifyPrimitive(obj) 61 | } 62 | 63 | export { 64 | stringify 65 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mpvue-router-patch 2 | > 在 mpvue 中使用 vue-router 兼容的路由写法 3 | 4 | [![npm package](https://img.shields.io/npm/v/mpvue-router-patch.svg)](https://npmjs.org/package/mpvue-router-patch) 5 | [![npm downloads](http://img.shields.io/npm/dm/mpvue-router-patch.svg)](https://npmjs.org/package/mpvue-router-patch) 6 | 7 | ## 安装 8 | 9 | ``` bash 10 | npm i mpvue-router-patch 11 | ``` 12 | 13 | ## 使用 14 | 15 | ``` js 16 | // main.js 17 | import Vue from 'vue' 18 | import MpvueRouterPatch from 'mpvue-router-patch' 19 | 20 | Vue.use(MpvueRouterPatch) 21 | ``` 22 | 23 | ## API 24 | 25 | > 支持以下列出的方法及属性 26 | 27 | ### Router 实例 28 | 29 | #### 属性 30 | 31 | * $router.app 32 | 33 | 当前页面的 Vue 实例 34 | 35 | * $router.mode 36 | 37 | 路由使用的模式,固定值 `history` 38 | 39 | * $router.currentRoute 40 | 41 | 当前路由对应的路由信息对象,等价于 $route 42 | 43 | #### 方法 44 | 45 | * $router.push(location, onComplete?, onAbort?, onSuccess?) 46 | 47 | 跳转到应用内的某个页面,`mpvue.navigateTo`、`mpvue.switchTab` 及 `mpvue.reLaunch` 均通过该方法实现,`location` 参数支持字符串及对象两种形式,跳转至 `tabBar` 页面或重启至某页面时必须以对象形式传入 48 | 49 | ``` js 50 | // 字符串 51 | router.push('/pages/news/detail') 52 | 53 | // 对象 54 | router.push({ path: '/pages/news/detail' }) 55 | 56 | // 带查询参数,变成 /pages/news/detail?id=1 57 | router.push({ path: '/pages/news/detail', query: { id: 1 } }) 58 | 59 | // 切换至 tabBar 页面 60 | router.push({ path: '/pages/news/list', isTab: true }) 61 | 62 | // 重启至某页面,无需指定是否为 tabBar 页面,但 tabBar 页面无法携带参数 63 | router.push({ path: '/pages/news/list', reLaunch: true }) 64 | ``` 65 | 66 | * $router.replace(location, onComplete?, onAbort?, onSuccess?) 67 | 68 | 关闭当前页面,跳转到应用内的某个页面,相当于 `mpvue.redirectTo`,`location` 参数格式与 `$router.push` 相似,不支持 `isTab` 及 `reLaunch` 属性 69 | 70 | * $router.go(n) 71 | 72 | 关闭当前页面,返回上一页面或多级页面,`n` 为回退层数,默认值为 `1` 73 | 74 | * $router.back() 75 | 76 | 关闭当前页面,返回上一页面 77 | 78 | ### 路由信息对象 79 | 80 | #### 属性 81 | 82 | * $route.path 83 | 84 | 字符串,对应当前路由的路径,总是解析为绝对路径,如 `/pages/news/list` 85 | 86 | * $route.params 87 | 88 | 空对象,小程序不支持该属性 89 | 90 | * $route.query 91 | 92 | 一个 key/value 对象,表示 URL 查询参数。例如,对于路径 `/pages/news/detail?id=1`,则有 `$route.query.id == 1`,如果没有查询参数,则是个空对象。 93 | 94 | * $route.hash 95 | 96 | 空字符串,小程序不支持该属性 97 | 98 | * $route.fullPath 99 | 100 | 完成解析后的 URL,包含查询参数和 hash 的完整路径 101 | 102 | * $route.name 103 | 104 | 当前路由的名称,由 `path` 转化而来 105 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 2 | 3 | // Copyright Joyent, Inc. and other Node contributors. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the 7 | // "Software"), to deal in the Software without restriction, including 8 | // without limitation the rights to use, copy, modify, merge, publish, 9 | // distribute, sublicense, and/or sell copies of the Software, and to permit 10 | // persons to whom the Software is furnished to do so, subject to the 11 | // following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included 14 | // in all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 19 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | var stringifyPrimitive = function stringifyPrimitive(v) { 25 | switch (typeof v === 'undefined' ? 'undefined' : _typeof(v)) { 26 | case 'string': 27 | return v; 28 | 29 | case 'boolean': 30 | return v ? 'true' : 'false'; 31 | 32 | case 'number': 33 | return isFinite(v) ? v : ''; 34 | 35 | default: 36 | return ''; 37 | } 38 | }; 39 | 40 | function stringify(obj, sep, eq, name) { 41 | sep = sep || '&'; 42 | eq = eq || '='; 43 | if (obj === null) { 44 | obj = undefined; 45 | } 46 | 47 | if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object') { 48 | return Object.keys(obj).map(function (k) { 49 | var ks = stringifyPrimitive(k) + eq; 50 | if (Array.isArray(obj[k])) { 51 | return obj[k].map(function (v) { 52 | return ks + stringifyPrimitive(v); 53 | }).join(sep); 54 | } else { 55 | return ks + stringifyPrimitive(obj[k]); 56 | } 57 | }).filter(Boolean).join(sep); 58 | } 59 | 60 | if (!name) return ''; 61 | return stringifyPrimitive(name) + eq + stringifyPrimitive(obj); 62 | } 63 | 64 | function parseUrl(location) { 65 | if (typeof location === 'string') return location; 66 | 67 | var path = location.path, 68 | query = location.query; 69 | 70 | var queryStr = stringify(query); 71 | 72 | if (!queryStr) { 73 | return path; 74 | } 75 | 76 | return path + '?' + queryStr; 77 | } 78 | 79 | function parseRoute($mp) { 80 | var _$mp = $mp || {}; 81 | var path = _$mp.page && _$mp.page.route; 82 | return { 83 | path: '/' + path, 84 | params: {}, 85 | query: _$mp.query, 86 | hash: '', 87 | fullPath: parseUrl({ 88 | path: '/' + path, 89 | query: _$mp.query 90 | }), 91 | name: path && path.replace(/\/(\w)/g, function ($0, $1) { 92 | return $1.toUpperCase(); 93 | }) 94 | }; 95 | } 96 | 97 | function push(location, complete, fail, success) { 98 | var url = parseUrl(location); 99 | var params = { url: url, complete: complete, fail: fail, success: success }; 100 | 101 | if (location.isTab) { 102 | mpvue.switchTab(params); 103 | return; 104 | } 105 | if (location.reLaunch) { 106 | mpvue.reLaunch(params); 107 | return; 108 | } 109 | mpvue.navigateTo(params); 110 | } 111 | 112 | function replace(location, complete, fail, success) { 113 | var url = parseUrl(location); 114 | mpvue.redirectTo({ url: url, complete: complete, fail: fail, success: success }); 115 | } 116 | 117 | function go(delta) { 118 | mpvue.navigateBack({ delta: delta }); 119 | } 120 | 121 | function back() { 122 | mpvue.navigateBack(); 123 | } 124 | 125 | var _Vue = void 0; 126 | 127 | var index = { 128 | install: function install(Vue) { 129 | if (this.installed && _Vue === Vue) return; 130 | this.installed = true; 131 | 132 | _Vue = Vue; 133 | 134 | var _router = { 135 | mode: 'history', 136 | push: push, 137 | replace: replace, 138 | go: go, 139 | back: back 140 | }; 141 | 142 | Vue.mixin({ 143 | onLoad: function onLoad() { 144 | var $mp = this.$root.$mp; 145 | 146 | this._route = parseRoute($mp); 147 | }, 148 | onShow: function onShow() { 149 | _router.app = this; 150 | _router.currentRoute = this._route; 151 | } 152 | }); 153 | 154 | Object.defineProperty(Vue.prototype, '$router', { 155 | get: function get() { 156 | return _router; 157 | } 158 | }); 159 | 160 | Object.defineProperty(Vue.prototype, '$route', { 161 | get: function get() { 162 | return this._route; 163 | } 164 | }); 165 | } 166 | }; 167 | 168 | export default index; 169 | export { _Vue }; 170 | --------------------------------------------------------------------------------