diff --git a/dist/vue-router.common.js b/dist/vue-router.common.js index 03a6f3575..952b54959 100644 --- a/dist/vue-router.common.js +++ b/dist/vue-router.common.js @@ -111,7 +111,7 @@ var encodeReserveRE = /[!'()*]/g; var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); }; var commaRE = /%2C/g; -// fixed encodeURIComponent which is more comformant to RFC3986: +// fixed encodeURIComponent which is more conformant to RFC3986: // - escapes [!'()*] // - preserve commas var encode = function (str) { return encodeURIComponent(str) @@ -399,8 +399,8 @@ function guardEvent (e) { // don't redirect on right click if (e.button !== undefined && e.button !== 0) { return } // don't redirect if `target="_blank"` - if (e.target && e.target.getAttribute) { - var target = e.target.getAttribute('target'); + if (e.currentTarget && e.currentTarget.getAttribute) { + var target = e.currentTarget.getAttribute('target'); if (/\b_blank\b/i.test(target)) { return } } // this may be a Weex event which doesn't have this method @@ -470,11 +470,12 @@ function resolvePath ( base, append ) { - if (relative.charAt(0) === '/') { + var firstChar = relative.charAt(0); + if (firstChar === '/') { return relative } - if (relative.charAt(0) === '?' || relative.charAt(0) === '#') { + if (firstChar === '?' || firstChar === '#') { return base + relative } @@ -491,11 +492,9 @@ function resolvePath ( var segments = relative.replace(/^\//, '').split('/'); for (var i = 0; i < segments.length; i++) { var segment = segments[i]; - if (segment === '.') { - continue - } else if (segment === '..') { + if (segment === '..') { stack.pop(); - } else { + } else if (segment !== '.') { stack.push(segment); } } @@ -540,13 +539,14 @@ function cleanPath (path) { function createRouteMap ( routes, oldPathMap, - oldNameMap + oldNameMap, + overwriteNames ) { var pathMap = oldPathMap || Object.create(null); var nameMap = oldNameMap || Object.create(null); routes.forEach(function (route) { - addRouteRecord(pathMap, nameMap, route); + addRouteRecord(pathMap, nameMap, route, undefined, undefined, overwriteNames); }); return { @@ -560,7 +560,8 @@ function addRouteRecord ( nameMap, route, parent, - matchAs + matchAs, + overwriteNames ) { var path = route.path; var name = route.name; @@ -610,7 +611,7 @@ function addRouteRecord ( var childMatchAs = matchAs ? cleanPath((matchAs + "/" + (child.path))) : undefined; - addRouteRecord(pathMap, nameMap, child, record, childMatchAs); + addRouteRecord(pathMap, nameMap, child, record, childMatchAs, overwriteNames); }); } @@ -621,14 +622,14 @@ function addRouteRecord ( path: alias, children: route.children }; - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path); + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames); }); } else { var aliasRoute = { path: route.alias, children: route.children }; - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path); + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames); } } @@ -637,7 +638,7 @@ function addRouteRecord ( } if (name) { - if (!nameMap[name]) { + if (!nameMap[name] || overwriteNames) { nameMap[name] = record; } else if (process.env.NODE_ENV !== 'production' && !matchAs) { warn( @@ -1195,8 +1196,11 @@ function createMatcher (routes) { var pathMap = ref.pathMap; var nameMap = ref.nameMap; - function addRoutes (routes) { - createRouteMap(routes, pathMap, nameMap); + function addRoutes ( + routes, + overwriteNames + ) { + createRouteMap(routes, pathMap, nameMap, overwriteNames); } function match ( @@ -2259,8 +2263,8 @@ VueRouter.prototype.resolve = function resolve ( } }; -VueRouter.prototype.addRoutes = function addRoutes (routes) { - this.matcher.addRoutes(routes); +VueRouter.prototype.addRoutes = function addRoutes (routes, overwriteNames) { + this.matcher.addRoutes(routes, overwriteNames); if (this.history.current !== START) { this.history.transitionTo(this.history.getCurrentLocation()); } diff --git a/dist/vue-router.esm.js b/dist/vue-router.esm.js index ed7b78aa6..572b9dc5e 100644 --- a/dist/vue-router.esm.js +++ b/dist/vue-router.esm.js @@ -109,7 +109,7 @@ var encodeReserveRE = /[!'()*]/g; var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); }; var commaRE = /%2C/g; -// fixed encodeURIComponent which is more comformant to RFC3986: +// fixed encodeURIComponent which is more conformant to RFC3986: // - escapes [!'()*] // - preserve commas var encode = function (str) { return encodeURIComponent(str) @@ -397,8 +397,8 @@ function guardEvent (e) { // don't redirect on right click if (e.button !== undefined && e.button !== 0) { return } // don't redirect if `target="_blank"` - if (e.target && e.target.getAttribute) { - var target = e.target.getAttribute('target'); + if (e.currentTarget && e.currentTarget.getAttribute) { + var target = e.currentTarget.getAttribute('target'); if (/\b_blank\b/i.test(target)) { return } } // this may be a Weex event which doesn't have this method @@ -468,11 +468,12 @@ function resolvePath ( base, append ) { - if (relative.charAt(0) === '/') { + var firstChar = relative.charAt(0); + if (firstChar === '/') { return relative } - if (relative.charAt(0) === '?' || relative.charAt(0) === '#') { + if (firstChar === '?' || firstChar === '#') { return base + relative } @@ -489,11 +490,9 @@ function resolvePath ( var segments = relative.replace(/^\//, '').split('/'); for (var i = 0; i < segments.length; i++) { var segment = segments[i]; - if (segment === '.') { - continue - } else if (segment === '..') { + if (segment === '..') { stack.pop(); - } else { + } else if (segment !== '.') { stack.push(segment); } } @@ -538,13 +537,14 @@ function cleanPath (path) { function createRouteMap ( routes, oldPathMap, - oldNameMap + oldNameMap, + overwriteNames ) { var pathMap = oldPathMap || Object.create(null); var nameMap = oldNameMap || Object.create(null); routes.forEach(function (route) { - addRouteRecord(pathMap, nameMap, route); + addRouteRecord(pathMap, nameMap, route, undefined, undefined, overwriteNames); }); return { @@ -558,7 +558,8 @@ function addRouteRecord ( nameMap, route, parent, - matchAs + matchAs, + overwriteNames ) { var path = route.path; var name = route.name; @@ -608,7 +609,7 @@ function addRouteRecord ( var childMatchAs = matchAs ? cleanPath((matchAs + "/" + (child.path))) : undefined; - addRouteRecord(pathMap, nameMap, child, record, childMatchAs); + addRouteRecord(pathMap, nameMap, child, record, childMatchAs, overwriteNames); }); } @@ -619,14 +620,14 @@ function addRouteRecord ( path: alias, children: route.children }; - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path); + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames); }); } else { var aliasRoute = { path: route.alias, children: route.children }; - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path); + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames); } } @@ -635,7 +636,7 @@ function addRouteRecord ( } if (name) { - if (!nameMap[name]) { + if (!nameMap[name] || overwriteNames) { nameMap[name] = record; } else if (process.env.NODE_ENV !== 'production' && !matchAs) { warn( @@ -1193,8 +1194,11 @@ function createMatcher (routes) { var pathMap = ref.pathMap; var nameMap = ref.nameMap; - function addRoutes (routes) { - createRouteMap(routes, pathMap, nameMap); + function addRoutes ( + routes, + overwriteNames + ) { + createRouteMap(routes, pathMap, nameMap, overwriteNames); } function match ( @@ -2257,8 +2261,8 @@ VueRouter.prototype.resolve = function resolve ( } }; -VueRouter.prototype.addRoutes = function addRoutes (routes) { - this.matcher.addRoutes(routes); +VueRouter.prototype.addRoutes = function addRoutes (routes, overwriteNames) { + this.matcher.addRoutes(routes, overwriteNames); if (this.history.current !== START) { this.history.transitionTo(this.history.getCurrentLocation()); } diff --git a/dist/vue-router.js b/dist/vue-router.js index e65acba2b..5026b5d1f 100644 --- a/dist/vue-router.js +++ b/dist/vue-router.js @@ -115,7 +115,7 @@ var encodeReserveRE = /[!'()*]/g; var encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); }; var commaRE = /%2C/g; -// fixed encodeURIComponent which is more comformant to RFC3986: +// fixed encodeURIComponent which is more conformant to RFC3986: // - escapes [!'()*] // - preserve commas var encode = function (str) { return encodeURIComponent(str) @@ -403,8 +403,8 @@ function guardEvent (e) { // don't redirect on right click if (e.button !== undefined && e.button !== 0) { return } // don't redirect if `target="_blank"` - if (e.target && e.target.getAttribute) { - var target = e.target.getAttribute('target'); + if (e.currentTarget && e.currentTarget.getAttribute) { + var target = e.currentTarget.getAttribute('target'); if (/\b_blank\b/i.test(target)) { return } } // this may be a Weex event which doesn't have this method @@ -474,11 +474,12 @@ function resolvePath ( base, append ) { - if (relative.charAt(0) === '/') { + var firstChar = relative.charAt(0); + if (firstChar === '/') { return relative } - if (relative.charAt(0) === '?' || relative.charAt(0) === '#') { + if (firstChar === '?' || firstChar === '#') { return base + relative } @@ -495,11 +496,9 @@ function resolvePath ( var segments = relative.replace(/^\//, '').split('/'); for (var i = 0; i < segments.length; i++) { var segment = segments[i]; - if (segment === '.') { - continue - } else if (segment === '..') { + if (segment === '..') { stack.pop(); - } else { + } else if (segment !== '.') { stack.push(segment); } } @@ -544,13 +543,14 @@ function cleanPath (path) { function createRouteMap ( routes, oldPathMap, - oldNameMap + oldNameMap, + overwriteNames ) { var pathMap = oldPathMap || Object.create(null); var nameMap = oldNameMap || Object.create(null); routes.forEach(function (route) { - addRouteRecord(pathMap, nameMap, route); + addRouteRecord(pathMap, nameMap, route, undefined, undefined, overwriteNames); }); return { @@ -564,7 +564,8 @@ function addRouteRecord ( nameMap, route, parent, - matchAs + matchAs, + overwriteNames ) { var path = route.path; var name = route.name; @@ -614,7 +615,7 @@ function addRouteRecord ( var childMatchAs = matchAs ? cleanPath((matchAs + "/" + (child.path))) : undefined; - addRouteRecord(pathMap, nameMap, child, record, childMatchAs); + addRouteRecord(pathMap, nameMap, child, record, childMatchAs, overwriteNames); }); } @@ -625,14 +626,14 @@ function addRouteRecord ( path: alias, children: route.children }; - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path); + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames); }); } else { var aliasRoute = { path: route.alias, children: route.children }; - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path); + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames); } } @@ -641,7 +642,7 @@ function addRouteRecord ( } if (name) { - if (!nameMap[name]) { + if (!nameMap[name] || overwriteNames) { nameMap[name] = record; } else if ("development" !== 'production' && !matchAs) { warn( @@ -1199,8 +1200,11 @@ function createMatcher (routes) { var pathMap = ref.pathMap; var nameMap = ref.nameMap; - function addRoutes (routes) { - createRouteMap(routes, pathMap, nameMap); + function addRoutes ( + routes, + overwriteNames + ) { + createRouteMap(routes, pathMap, nameMap, overwriteNames); } function match ( @@ -2263,8 +2267,8 @@ VueRouter.prototype.resolve = function resolve ( } }; -VueRouter.prototype.addRoutes = function addRoutes (routes) { - this.matcher.addRoutes(routes); +VueRouter.prototype.addRoutes = function addRoutes (routes, overwriteNames) { + this.matcher.addRoutes(routes, overwriteNames); if (this.history.current !== START) { this.history.transitionTo(this.history.getCurrentLocation()); } diff --git a/dist/vue-router.min.js b/dist/vue-router.min.js index 9d5a9d396..e738c87e7 100644 --- a/dist/vue-router.min.js +++ b/dist/vue-router.min.js @@ -3,4 +3,4 @@ * (c) 2017 Evan You * @license MIT */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.VueRouter=e()}(this,function(){"use strict";function t(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function e(e,n){switch(typeof n){case"undefined":return;case"object":return n;case"function":return n(e);case"boolean":return n?e.params:void 0;default:t(!1,'props in "'+e.path+'" is a '+typeof n+", expecting an object, function or boolean.")}}function n(t,e){if(void 0===e&&(e={}),t){var n;try{n=r(t)}catch(t){n={}}for(var o in e)n[o]=e[o];return n}return e}function r(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=_t(n.shift()),o=n.length>0?_t(n.join("=")):null;void 0===e[r]?e[r]=o:Array.isArray(e[r])?e[r].push(o):e[r]=[e[r],o]}),e):e}function o(t){var e=t?Object.keys(t).map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return Ct(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(Ct(e)):r.push(Ct(e)+"="+Ct(t)))}),r.join("&")}return Ct(e)+"="+Ct(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function i(t,e,n){var r={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:e.query||{},params:e.params||{},fullPath:u(e),matched:t?a(t):[]};return n&&(r.redirectedFrom=u(n)),Object.freeze(r)}function a(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function u(t){var e=t.path,n=t.query;void 0===n&&(n={});var r=t.hash;return void 0===r&&(r=""),(e||"/")+o(n)+r}function c(t,e){return e===$t?t===e:!!e&&(t.path&&e.path?t.path.replace(Tt,"")===e.path.replace(Tt,"")&&t.hash===e.hash&&s(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&s(t.query,e.query)&&s(t.params,e.params)))}function s(t,e){void 0===t&&(t={}),void 0===e&&(e={});var n=Object.keys(t),r=Object.keys(e);return n.length===r.length&&n.every(function(n){return String(t[n])===String(e[n])})}function p(t,e){return 0===t.path.replace(Tt,"/").indexOf(e.path.replace(Tt,"/"))&&(!e.hash||t.hash===e.hash)&&f(t.query,e.query)}function f(t,e){for(var n in e)if(!(n in t))return!1;return!0}function h(t){if(!(t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.target&&t.target.getAttribute){var e=t.target.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function l(t){if(t)for(var e,n=0;n=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}function m(t){return t.replace(/\/\//g,"/")}function g(t,e,n){var r=e||Object.create(null),o=n||Object.create(null);return t.forEach(function(t){w(r,o,t)}),{pathMap:r,nameMap:o}}function w(t,e,n,r,o){var i=n.path,a=n.name,u={path:b(i,r),components:n.components||{default:n.component},instances:{},name:a,parent:r,matchAs:o,redirect:n.redirect,beforeEnter:n.beforeEnter,meta:n.meta||{},props:null==n.props?{}:n.components?n.props:{default:n.props}};if(n.children&&n.children.forEach(function(n){var r=o?m(o+"/"+n.path):void 0;w(t,e,n,u,r)}),void 0!==n.alias)if(Array.isArray(n.alias))n.alias.forEach(function(o){var i={path:o,children:n.children};w(t,e,i,r,u.path)});else{var c={path:n.alias,children:n.children};w(t,e,c,r,u.path)}t[u.path]||(t[u.path]=u),a&&(e[a]||(e[a]=u))}function b(t,e){return t=t.replace(/\/$/,""),"/"===t[0]?t:null==e?t:m(e.path+"/"+t)}function x(t,e){for(var n,r=[],o=0,i=0,a="",u=e&&e.delimiter||"/";null!=(n=Ft.exec(t));){var c=n[0],s=n[1],p=n.index;if(a+=t.slice(i,p),i=p+c.length,s)a+=s[1];else{var f=t[i],h=n[2],l=n[3],d=n[4],y=n[5],v=n[6],m=n[7];a&&(r.push(a),a="");var g=null!=h&&null!=f&&f!==h,w="+"===v||"*"===v,b="?"===v||"*"===v,x=n[2]||u,k=d||y;r.push({name:l||o++,prefix:h||"",delimiter:x,optional:b,repeat:w,partial:g,asterisk:!!m,pattern:k?A(k):m?".*":"[^"+j(x)+"]+?"})}}return i-1&&(r.params[c]=e.params[c]);if(i)return r.path=U(i.path,r.params,'named route "'+o+'"'),u(i,r,n)}else if(r.path){r.params={};for(var f in s)if(B(f,r.params,r.path))return u(s[f],r,n)}return u(null,r)}function o(e,n){var o=e.redirect,a="function"==typeof o?o(i(e,n)):o;if("string"==typeof a&&(a={path:a}),!a||"object"!=typeof a)return u(null,n);var c=a,s=c.name,f=c.path,h=n.query,l=n.hash,d=n.params;if(h=c.hasOwnProperty("query")?c.query:h,l=c.hasOwnProperty("hash")?c.hash:l,d=c.hasOwnProperty("params")?c.params:d,s){p[s];return r({_normalized:!0,name:s,query:h,hash:l,params:d},void 0,n)}if(f){var y=H(f,e),v=U(y,d,'redirect route with path "'+y+'"');return r({_normalized:!0,path:v,query:h,hash:l},void 0,n)}return t(!1,"invalid redirect option: "+JSON.stringify(a)),u(null,n)}function a(t,e,n){var o=U(n,e.params,'aliased route with path "'+n+'"'),i=r({_normalized:!0,path:o});if(i){var a=i.matched,c=a[a.length-1];return e.params=i.params,u(c,e)}return u(null,e)}function u(t,e,n){return t&&t.redirect?o(t,n||e):t&&t.matchAs?a(t,e,t.matchAs):i(t,e,n)}var c=g(e),s=c.pathMap,p=c.nameMap;return{match:r,addRoutes:n}}function B(t,e,n){var r=P(t),o=r.regexp,i=r.keys,a=n.match(o);if(!a)return!1;if(!e)return!0;for(var u=1,c=a.length;u=t.length?n():t[o]?e(t[o],function(){r(o+1)}):r(o+1)};r(0)}function nt(t){if(!t)if(Pt){var e=document.querySelector("base");t=e&&e.getAttribute("href")||"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function rt(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}function kt(t,e,n){var r="hash"===n?"#"+e:e;return t?m(t+"/"+r):r}var Ot,Rt={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,n){var r=n.props,o=n.children,i=n.parent,a=n.data;a.routerView=!0;for(var u=r.name,c=i.$route,s=i._routerViewCache||(i._routerViewCache={}),p=0,f=!1;i;)i.$vnode&&i.$vnode.data.routerView&&p++,i._inactive&&(f=!0),i=i.$parent;if(a.routerViewDepth=p,f)return t(s[u],a,o);var h=c.matched[p];if(!h)return s[u]=null,t();var l=s[u]=h.components[u],d=a.hook||(a.hook={});return d.init=function(t){h.instances[u]=t.child},d.prepatch=function(t,e){h.instances[u]=e.child},d.destroy=function(t){h.instances[u]===t.child&&(h.instances[u]=void 0)},a.props=e(c,h.props&&h.props[u]),t(l,a,o)}},Et=/[!'()*]/g,jt=function(t){return"%"+t.charCodeAt(0).toString(16)},At=/%2C/g,Ct=function(t){return encodeURIComponent(t).replace(Et,jt).replace(At,",")},_t=decodeURIComponent,Tt=/\/?$/,$t=i(null,{path:"/"}),St=[String,Object],qt=[String,Array],Lt={name:"router-link",props:{to:{type:St,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String,event:{type:qt,default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),a=o.location,u=o.route,s=o.href,f={},d=this.activeClass||n.options.linkActiveClass||"router-link-active",y=a.path?i(null,a):u;f[d]=this.exact?c(r,y):p(r,y);var v=function(t){h(t)&&(e.replace?n.replace(a):n.push(a))},m={click:h};Array.isArray(this.event)?this.event.forEach(function(t){m[t]=v}):m[this.event]=v;var g={class:f};if("a"===this.tag)g.on=m,g.attrs={href:s};else{var w=l(this.$slots.default);if(w){w.isStatic=!1;var b=Ot.util.extend,x=w.data=b({},w.data);x.on=m;var k=w.data.attrs=b({},w.data.attrs);k.href=s}else g.on=m}return t(this.tag,g,this.$slots.default)}},Pt="undefined"!=typeof window,Ut=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},zt=Ut,Mt=L,Vt=x,Bt=k,Ht=E,It=q,Ft=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");Mt.parse=Vt,Mt.compile=Bt,Mt.tokensToFunction=Ht,Mt.tokensToRegExp=It;var Dt=Object.create(null),Jt=Object.create(null),Kt=Object.create(null),Nt=Pt&&function(){var t=window.navigator.userAgent;return(t.indexOf("Android 2.")===-1&&t.indexOf("Android 4.0")===-1||t.indexOf("Mobile Safari")===-1||t.indexOf("Chrome")!==-1||t.indexOf("Windows Phone")!==-1)&&(window.history&&"pushState"in window.history)}(),Xt=Pt&&window.performance&&window.performance.now?window.performance:Date,Yt=W(),Wt=function(t,e){this.router=t,this.base=nt(e),this.current=$t,this.pending=null,this.ready=!1,this.readyCbs=[]};Wt.prototype.listen=function(t){this.cb=t},Wt.prototype.onReady=function(t){this.ready?t():this.readyCbs.push(t)},Wt.prototype.transitionTo=function(t,e,n){var r=this,o=this.router.match(t,this.current);this.confirmTransition(o,function(){r.updateRoute(o),e&&e(o),r.ensureURL(),r.ready||(r.ready=!0,r.readyCbs.forEach(function(t){t(o)}))},n)},Wt.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current,i=function(){n&&n()};if(c(t,o)&&t.matched.length===o.matched.length)return this.ensureURL(),i();var a=rt(this.current.matched,t.matched),u=a.updated,s=a.deactivated,p=a.activated,f=[].concat(at(s),this.router.beforeHooks,ut(u),p.map(function(t){return t.beforeEnter}),ht(p));this.pending=t;var h=function(e,n){return r.pending!==t?i():void e(t,o,function(t){t===!1?(r.ensureURL(!0),i()):"string"==typeof t||"object"==typeof t?("object"==typeof t&&t.replace?r.replace(t):r.push(t),i()):n(t)})};et(f,h,function(){var n=[],o=function(){return r.current===t},a=st(p,n,o);et(a,h,function(){return r.pending!==t?i():(r.pending=null,e(t),void(r.router.app&&r.router.app.$nextTick(function(){n.forEach(function(t){return t()})})))})})},Wt.prototype.updateRoute=function(t){var e=this.current;this.current=t,this.cb&&this.cb(t),this.router.afterHooks.forEach(function(n){n&&n(t,e)})};var Gt=function(t){function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavior;o&&I(),window.addEventListener("popstate",function(t){r.transitionTo(vt(r.base),function(t){o&&F(e,t,r.current,!0)})})}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this,i=o.current;this.transitionTo(t,function(t){Z(m(r.base+t.fullPath)),F(r.router,t,i,!1),e&&e(t)},n)},e.prototype.replace=function(t,e,n){var r=this,o=this,i=o.current;this.transitionTo(t,function(t){tt(m(r.base+t.fullPath)),F(r.router,t,i,!1),e&&e(t)},n)},e.prototype.ensureURL=function(t){if(vt(this.base)!==this.current.fullPath){var e=m(this.base+this.current.fullPath);t?Z(e):tt(e)}},e.prototype.getCurrentLocation=function(){return vt(this.base)},e}(Wt),Qt=function(t){function e(e,n,r){t.call(this,e,n),r&&mt(this.base)||gt()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;window.addEventListener("hashchange",function(){gt()&&t.transitionTo(wt(),function(t){xt(t.fullPath)})})},e.prototype.push=function(t,e,n){this.transitionTo(t,function(t){bt(t.fullPath),e&&e(t)},n)},e.prototype.replace=function(t,e,n){this.transitionTo(t,function(t){xt(t.fullPath),e&&e(t)},n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;wt()!==e&&(t?bt(e):xt(e))},e.prototype.getCurrentLocation=function(){return wt()},e}(Wt),Zt=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)},n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)},n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,function(){e.index=n,e.updateRoute(r)})}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Wt),te=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.afterHooks=[],this.matcher=V(t.routes||[]);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Nt,this.fallback&&(e="hash"),Pt||(e="abstract"),this.mode=e,e){case"history":this.history=new Gt(this,t.base);break;case"hash":this.history=new Qt(this,t.base,this.fallback);break;case"abstract":this.history=new Zt(this,t.base)}},ee={currentRoute:{}};return te.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},ee.currentRoute.get=function(){return this.history&&this.history.current},te.prototype.init=function(t){var e=this;if(this.apps.push(t),!this.app){this.app=t;var n=this.history;if(n instanceof Gt)n.transitionTo(n.getCurrentLocation());else if(n instanceof Qt){var r=function(){n.setupListeners()};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen(function(t){e.apps.forEach(function(e){e._route=t})})}},te.prototype.beforeEach=function(t){this.beforeHooks.push(t)},te.prototype.afterEach=function(t){this.afterHooks.push(t)},te.prototype.onReady=function(t){this.history.onReady(t)},te.prototype.push=function(t,e,n){this.history.push(t,e,n)},te.prototype.replace=function(t,e,n){this.history.replace(t,e,n)},te.prototype.go=function(t){this.history.go(t)},te.prototype.back=function(){this.go(-1)},te.prototype.forward=function(){this.go(1)},te.prototype.getMatchedComponents=function(t){var e=t?this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},te.prototype.resolve=function(t,e,n){var r=z(t,e||this.history.current,n),o=this.match(r,e),i=o.redirectedFrom||o.fullPath,a=this.history.base,u=kt(a,i,this.mode);return{location:r,route:o,href:u,normalizedTo:r,resolved:o}},te.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==$t&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(te.prototype,ee),te.install=d,te.version="2.3.1",Pt&&window.Vue&&window.Vue.use(te),te}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.VueRouter=e()}(this,function(){"use strict";function t(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function e(e,n){switch(typeof n){case"undefined":return;case"object":return n;case"function":return n(e);case"boolean":return n?e.params:void 0;default:t(!1,'props in "'+e.path+'" is a '+typeof n+", expecting an object, function or boolean.")}}function n(t,e){if(void 0===e&&(e={}),t){var n;try{n=r(t)}catch(t){n={}}for(var o in e)n[o]=e[o];return n}return e}function r(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=Ct(n.shift()),o=n.length>0?Ct(n.join("=")):null;void 0===e[r]?e[r]=o:Array.isArray(e[r])?e[r].push(o):e[r]=[e[r],o]}),e):e}function o(t){var e=t?Object.keys(t).map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return Tt(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(Tt(e)):r.push(Tt(e)+"="+Tt(t)))}),r.join("&")}return Tt(e)+"="+Tt(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function i(t,e,n){var r={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:e.query||{},params:e.params||{},fullPath:u(e),matched:t?a(t):[]};return n&&(r.redirectedFrom=u(n)),Object.freeze(r)}function a(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function u(t){var e=t.path,n=t.query;void 0===n&&(n={});var r=t.hash;return void 0===r&&(r=""),(e||"/")+o(n)+r}function c(t,e){return e===$t?t===e:!!e&&(t.path&&e.path?t.path.replace(_t,"")===e.path.replace(_t,"")&&t.hash===e.hash&&s(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&s(t.query,e.query)&&s(t.params,e.params)))}function s(t,e){void 0===t&&(t={}),void 0===e&&(e={});var n=Object.keys(t),r=Object.keys(e);return n.length===r.length&&n.every(function(n){return String(t[n])===String(e[n])})}function p(t,e){return 0===t.path.replace(_t,"/").indexOf(e.path.replace(_t,"/"))&&(!e.hash||t.hash===e.hash)&&f(t.query,e.query)}function f(t,e){for(var n in e)if(!(n in t))return!1;return!0}function h(t){if(!(t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){var e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function l(t){if(t)for(var e,n=0;n=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}function m(t){return t.replace(/\/\//g,"/")}function g(t,e,n,r){var o=e||Object.create(null),i=n||Object.create(null);return t.forEach(function(t){w(o,i,t,void 0,void 0,r)}),{pathMap:o,nameMap:i}}function w(t,e,n,r,o,i){var a=n.path,u=n.name,c={path:b(a,r),components:n.components||{default:n.component},instances:{},name:u,parent:r,matchAs:o,redirect:n.redirect,beforeEnter:n.beforeEnter,meta:n.meta||{},props:null==n.props?{}:n.components?n.props:{default:n.props}};if(n.children&&n.children.forEach(function(n){var r=o?m(o+"/"+n.path):void 0;w(t,e,n,c,r,i)}),void 0!==n.alias)if(Array.isArray(n.alias))n.alias.forEach(function(o){var a={path:o,children:n.children};w(t,e,a,r,c.path,i)});else{var s={path:n.alias,children:n.children};w(t,e,s,r,c.path,i)}t[c.path]||(t[c.path]=c),u&&(e[u]&&!i||(e[u]=c))}function b(t,e){return t=t.replace(/\/$/,""),"/"===t[0]?t:null==e?t:m(e.path+"/"+t)}function x(t,e){for(var n,r=[],o=0,i=0,a="",u=e&&e.delimiter||"/";null!=(n=Ft.exec(t));){var c=n[0],s=n[1],p=n.index;if(a+=t.slice(i,p),i=p+c.length,s)a+=s[1];else{var f=t[i],h=n[2],l=n[3],d=n[4],y=n[5],v=n[6],m=n[7];a&&(r.push(a),a="");var g=null!=h&&null!=f&&f!==h,w="+"===v||"*"===v,b="?"===v||"*"===v,x=n[2]||u,k=d||y;r.push({name:l||o++,prefix:h||"",delimiter:x,optional:b,repeat:w,partial:g,asterisk:!!m,pattern:k?A(k):m?".*":"[^"+j(x)+"]+?"})}}return i-1&&(r.params[c]=e.params[c]);if(i)return r.path=U(i.path,r.params,'named route "'+o+'"'),u(i,r,n)}else if(r.path){r.params={};for(var f in s)if(B(f,r.params,r.path))return u(s[f],r,n)}return u(null,r)}function o(e,n){var o=e.redirect,a="function"==typeof o?o(i(e,n)):o;if("string"==typeof a&&(a={path:a}),!a||"object"!=typeof a)return u(null,n);var c=a,s=c.name,f=c.path,h=n.query,l=n.hash,d=n.params;if(h=c.hasOwnProperty("query")?c.query:h,l=c.hasOwnProperty("hash")?c.hash:l,d=c.hasOwnProperty("params")?c.params:d,s){p[s];return r({_normalized:!0,name:s,query:h,hash:l,params:d},void 0,n)}if(f){var y=H(f,e),v=U(y,d,'redirect route with path "'+y+'"');return r({_normalized:!0,path:v,query:h,hash:l},void 0,n)}return t(!1,"invalid redirect option: "+JSON.stringify(a)),u(null,n)}function a(t,e,n){var o=U(n,e.params,'aliased route with path "'+n+'"'),i=r({_normalized:!0,path:o});if(i){var a=i.matched,c=a[a.length-1];return e.params=i.params,u(c,e)}return u(null,e)}function u(t,e,n){return t&&t.redirect?o(t,n||e):t&&t.matchAs?a(t,e,t.matchAs):i(t,e,n)}var c=g(e),s=c.pathMap,p=c.nameMap;return{match:r,addRoutes:n}}function B(t,e,n){var r=P(t),o=r.regexp,i=r.keys,a=n.match(o);if(!a)return!1;if(!e)return!0;for(var u=1,c=a.length;u=t.length?n():t[o]?e(t[o],function(){r(o+1)}):r(o+1)};r(0)}function nt(t){if(!t)if(Pt){var e=document.querySelector("base");t=e&&e.getAttribute("href")||"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function rt(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}function kt(t,e,n){var r="hash"===n?"#"+e:e;return t?m(t+"/"+r):r}var Ot,Rt={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,n){var r=n.props,o=n.children,i=n.parent,a=n.data;a.routerView=!0;for(var u=r.name,c=i.$route,s=i._routerViewCache||(i._routerViewCache={}),p=0,f=!1;i;)i.$vnode&&i.$vnode.data.routerView&&p++,i._inactive&&(f=!0),i=i.$parent;if(a.routerViewDepth=p,f)return t(s[u],a,o);var h=c.matched[p];if(!h)return s[u]=null,t();var l=s[u]=h.components[u],d=a.hook||(a.hook={});return d.init=function(t){h.instances[u]=t.child},d.prepatch=function(t,e){h.instances[u]=e.child},d.destroy=function(t){h.instances[u]===t.child&&(h.instances[u]=void 0)},a.props=e(c,h.props&&h.props[u]),t(l,a,o)}},Et=/[!'()*]/g,jt=function(t){return"%"+t.charCodeAt(0).toString(16)},At=/%2C/g,Tt=function(t){return encodeURIComponent(t).replace(Et,jt).replace(At,",")},Ct=decodeURIComponent,_t=/\/?$/,$t=i(null,{path:"/"}),St=[String,Object],qt=[String,Array],Lt={name:"router-link",props:{to:{type:St,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String,event:{type:qt,default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),a=o.location,u=o.route,s=o.href,f={},d=this.activeClass||n.options.linkActiveClass||"router-link-active",y=a.path?i(null,a):u;f[d]=this.exact?c(r,y):p(r,y);var v=function(t){h(t)&&(e.replace?n.replace(a):n.push(a))},m={click:h};Array.isArray(this.event)?this.event.forEach(function(t){m[t]=v}):m[this.event]=v;var g={class:f};if("a"===this.tag)g.on=m,g.attrs={href:s};else{var w=l(this.$slots.default);if(w){w.isStatic=!1;var b=Ot.util.extend,x=w.data=b({},w.data);x.on=m;var k=w.data.attrs=b({},w.data.attrs);k.href=s}else g.on=m}return t(this.tag,g,this.$slots.default)}},Pt="undefined"!=typeof window,Ut=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},zt=Ut,Mt=L,Vt=x,Bt=k,Ht=E,It=q,Ft=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");Mt.parse=Vt,Mt.compile=Bt,Mt.tokensToFunction=Ht,Mt.tokensToRegExp=It;var Dt=Object.create(null),Jt=Object.create(null),Kt=Object.create(null),Nt=Pt&&function(){var t=window.navigator.userAgent;return(t.indexOf("Android 2.")===-1&&t.indexOf("Android 4.0")===-1||t.indexOf("Mobile Safari")===-1||t.indexOf("Chrome")!==-1||t.indexOf("Windows Phone")!==-1)&&(window.history&&"pushState"in window.history)}(),Xt=Pt&&window.performance&&window.performance.now?window.performance:Date,Yt=W(),Wt=function(t,e){this.router=t,this.base=nt(e),this.current=$t,this.pending=null,this.ready=!1,this.readyCbs=[]};Wt.prototype.listen=function(t){this.cb=t},Wt.prototype.onReady=function(t){this.ready?t():this.readyCbs.push(t)},Wt.prototype.transitionTo=function(t,e,n){var r=this,o=this.router.match(t,this.current);this.confirmTransition(o,function(){r.updateRoute(o),e&&e(o),r.ensureURL(),r.ready||(r.ready=!0,r.readyCbs.forEach(function(t){t(o)}))},n)},Wt.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current,i=function(){n&&n()};if(c(t,o)&&t.matched.length===o.matched.length)return this.ensureURL(),i();var a=rt(this.current.matched,t.matched),u=a.updated,s=a.deactivated,p=a.activated,f=[].concat(at(s),this.router.beforeHooks,ut(u),p.map(function(t){return t.beforeEnter}),ht(p));this.pending=t;var h=function(e,n){return r.pending!==t?i():void e(t,o,function(t){t===!1?(r.ensureURL(!0),i()):"string"==typeof t||"object"==typeof t?("object"==typeof t&&t.replace?r.replace(t):r.push(t),i()):n(t)})};et(f,h,function(){var n=[],o=function(){return r.current===t},a=st(p,n,o);et(a,h,function(){return r.pending!==t?i():(r.pending=null,e(t),void(r.router.app&&r.router.app.$nextTick(function(){n.forEach(function(t){return t()})})))})})},Wt.prototype.updateRoute=function(t){var e=this.current;this.current=t,this.cb&&this.cb(t),this.router.afterHooks.forEach(function(n){n&&n(t,e)})};var Gt=function(t){function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavior;o&&I(),window.addEventListener("popstate",function(t){r.transitionTo(vt(r.base),function(t){o&&F(e,t,r.current,!0)})})}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this,i=o.current;this.transitionTo(t,function(t){Z(m(r.base+t.fullPath)),F(r.router,t,i,!1),e&&e(t)},n)},e.prototype.replace=function(t,e,n){var r=this,o=this,i=o.current;this.transitionTo(t,function(t){tt(m(r.base+t.fullPath)),F(r.router,t,i,!1),e&&e(t)},n)},e.prototype.ensureURL=function(t){if(vt(this.base)!==this.current.fullPath){var e=m(this.base+this.current.fullPath);t?Z(e):tt(e)}},e.prototype.getCurrentLocation=function(){return vt(this.base)},e}(Wt),Qt=function(t){function e(e,n,r){t.call(this,e,n),r&&mt(this.base)||gt()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;window.addEventListener("hashchange",function(){gt()&&t.transitionTo(wt(),function(t){xt(t.fullPath)})})},e.prototype.push=function(t,e,n){this.transitionTo(t,function(t){bt(t.fullPath),e&&e(t)},n)},e.prototype.replace=function(t,e,n){this.transitionTo(t,function(t){xt(t.fullPath),e&&e(t)},n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;wt()!==e&&(t?bt(e):xt(e))},e.prototype.getCurrentLocation=function(){return wt()},e}(Wt),Zt=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)},n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)},n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,function(){e.index=n,e.updateRoute(r)})}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Wt),te=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.afterHooks=[],this.matcher=V(t.routes||[]);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Nt,this.fallback&&(e="hash"),Pt||(e="abstract"),this.mode=e,e){case"history":this.history=new Gt(this,t.base);break;case"hash":this.history=new Qt(this,t.base,this.fallback);break;case"abstract":this.history=new Zt(this,t.base)}},ee={currentRoute:{}};return te.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},ee.currentRoute.get=function(){return this.history&&this.history.current},te.prototype.init=function(t){var e=this;if(this.apps.push(t),!this.app){this.app=t;var n=this.history;if(n instanceof Gt)n.transitionTo(n.getCurrentLocation());else if(n instanceof Qt){var r=function(){n.setupListeners()};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen(function(t){e.apps.forEach(function(e){e._route=t})})}},te.prototype.beforeEach=function(t){this.beforeHooks.push(t)},te.prototype.afterEach=function(t){this.afterHooks.push(t)},te.prototype.onReady=function(t){this.history.onReady(t)},te.prototype.push=function(t,e,n){this.history.push(t,e,n)},te.prototype.replace=function(t,e,n){this.history.replace(t,e,n)},te.prototype.go=function(t){this.history.go(t)},te.prototype.back=function(){this.go(-1)},te.prototype.forward=function(){this.go(1)},te.prototype.getMatchedComponents=function(t){var e=t?this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},te.prototype.resolve=function(t,e,n){var r=z(t,e||this.history.current,n),o=this.match(r,e),i=o.redirectedFrom||o.fullPath,a=this.history.base,u=kt(a,i,this.mode);return{location:r,route:o,href:u,normalizedTo:r,resolved:o}},te.prototype.addRoutes=function(t,e){this.matcher.addRoutes(t,e),this.history.current!==$t&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(te.prototype,ee),te.install=d,te.version="2.3.1",Pt&&window.Vue&&window.Vue.use(te),te}); \ No newline at end of file diff --git a/src/create-matcher.js b/src/create-matcher.js index 7fe0436f5..79a8d950d 100644 --- a/src/create-matcher.js +++ b/src/create-matcher.js @@ -9,14 +9,17 @@ import { getRouteRegex, fillParams } from './util/params' export type Matcher = { match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route; - addRoutes: (routes: Array) => void; + addRoutes: (routes: Array, overwriteNames?: boolean) => void; }; export function createMatcher (routes: Array): Matcher { const { pathMap, nameMap } = createRouteMap(routes) - function addRoutes (routes) { - createRouteMap(routes, pathMap, nameMap) + function addRoutes ( + routes, + overwriteNames?: boolean + ) { + createRouteMap(routes, pathMap, nameMap, overwriteNames) } function match ( diff --git a/src/create-route-map.js b/src/create-route-map.js index d3c1fa747..945bfab17 100644 --- a/src/create-route-map.js +++ b/src/create-route-map.js @@ -6,7 +6,8 @@ import { cleanPath } from './util/path' export function createRouteMap ( routes: Array, oldPathMap?: Dictionary, - oldNameMap?: Dictionary + oldNameMap?: Dictionary, + overwriteNames?: boolean ): { pathMap: Dictionary; nameMap: Dictionary; @@ -15,7 +16,7 @@ export function createRouteMap ( const nameMap: Dictionary = oldNameMap || Object.create(null) routes.forEach(route => { - addRouteRecord(pathMap, nameMap, route) + addRouteRecord(pathMap, nameMap, route, undefined, undefined, overwriteNames) }) return { @@ -29,7 +30,8 @@ function addRouteRecord ( nameMap: Dictionary, route: RouteConfig, parent?: RouteRecord, - matchAs?: string + matchAs?: string, + overwriteNames?: boolean ) { const { path, name } = route if (process.env.NODE_ENV !== 'production') { @@ -78,7 +80,7 @@ function addRouteRecord ( const childMatchAs = matchAs ? cleanPath(`${matchAs}/${child.path}`) : undefined - addRouteRecord(pathMap, nameMap, child, record, childMatchAs) + addRouteRecord(pathMap, nameMap, child, record, childMatchAs, overwriteNames) }) } @@ -89,14 +91,14 @@ function addRouteRecord ( path: alias, children: route.children } - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path) + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames) }) } else { const aliasRoute = { path: route.alias, children: route.children } - addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path) + addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path, overwriteNames) } } @@ -105,7 +107,7 @@ function addRouteRecord ( } if (name) { - if (!nameMap[name]) { + if (!nameMap[name] || overwriteNames) { nameMap[name] = record } else if (process.env.NODE_ENV !== 'production' && !matchAs) { warn( diff --git a/src/index.js b/src/index.js index 0d0d26252..71fa39135 100644 --- a/src/index.js +++ b/src/index.js @@ -189,8 +189,8 @@ export default class VueRouter { } } - addRoutes (routes: Array) { - this.matcher.addRoutes(routes) + addRoutes (routes: Array, overwriteNames?: boolean) { + this.matcher.addRoutes(routes, overwriteNames) if (this.history.current !== START) { this.history.transitionTo(this.history.getCurrentLocation()) } diff --git a/test/unit/specs/api.spec.js b/test/unit/specs/api.spec.js index 57e912cd9..c4f3ee721 100644 --- a/test/unit/specs/api.spec.js +++ b/test/unit/specs/api.spec.js @@ -49,7 +49,7 @@ describe('router.addRoutes', () => { const router = new Router({ mode: 'abstract', routes: [ - { path: '/a', component: { name: 'A' }} + { path: '/a', component: { name: 'A' }, name: 'routeA' } ] }) @@ -63,7 +63,7 @@ describe('router.addRoutes', () => { expect(components.length).toBe(0) router.addRoutes([ - { path: '/b', component: { name: 'B' }} + { path: '/b', component: { name: 'B' }, name: 'routeB' } ]) components = router.getMatchedComponents() expect(components.length).toBe(1) @@ -74,6 +74,54 @@ describe('router.addRoutes', () => { components = router.getMatchedComponents() expect(components.length).toBe(1) expect(components[0].name).toBe('A') + + // adding same name route with overwriteNames parameter set to true + router.addRoutes([ + { path: '/c', component: { name: 'C' }, name: 'routeA' } + ], true) + router.push({ name: 'routeA' }) + components = router.getMatchedComponents() + expect(components.length).toBe(1) + expect(components[0].name).toBe('C') + expect(router.currentRoute.path).toBe('/c') + expect(router.currentRoute.name).toBe('routeA') + + // overwriting a route name with a nested route name + router.addRoutes([ + { + path: '/d', + name: 'routeD', + component: { name: 'D' }, + children: [ + { + path: 'e', + component: { name: 'E' }, + name: 'routeB' + } + ] + } + ], true) + router.push({ name: 'routeB' }) + components = router.getMatchedComponents() + expect(components.length).toBe(2) + expect(components[0].name).toBe('D') + expect(components[1].name).toBe('E') + expect(router.currentRoute.path).toBe('/d/e') + expect(router.currentRoute.name).toBe('routeB') + + // make sure it preserves previous routes + router.push('/a') + components = router.getMatchedComponents() + expect(components.length).toBe(1) + expect(components[0].name).toBe('A') + expect(router.currentRoute.path).toBe('/a') + expect(router.currentRoute.name).toBe('routeA') + router.push('/b') + components = router.getMatchedComponents() + expect(components.length).toBe(1) + expect(components[0].name).toBe('B') + expect(router.currentRoute.path).toBe('/b') + expect(router.currentRoute.name).toBe('routeB') }) }) diff --git a/types/router.d.ts b/types/router.d.ts index 60ad25e2c..d3e11f777 100644 --- a/types/router.d.ts +++ b/types/router.d.ts @@ -29,7 +29,7 @@ declare class VueRouter { forward (): void; getMatchedComponents (to?: RawLocation): Component[]; onReady (cb: Function): void; - addRoutes (routes: RouteConfig[]): void; + addRoutes (routes: RouteConfig[], overwriteNames?: boolean): void; resolve (to: RawLocation, current?: Route, append?: boolean): { location: Location; route: Route; diff --git a/yarn.lock b/yarn.lock index 48c40134f..c4b4839a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -893,8 +893,8 @@ caniuse-api@^1.5.2: lodash.uniq "^4.3.0" caniuse-db@^1.0.30000346, caniuse-db@^1.0.30000624: - version "1.0.30000626" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000626.tgz#44363dc86857efaf758fea9faef6a15ed93d8f33" + version "1.0.30000628" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000628.tgz#3d010e2a8e2537a8d135792e90e4f2ce0eb838cc" caseless@~0.11.0: version "0.11.0" @@ -1196,8 +1196,8 @@ create-hmac@^1.1.0, create-hmac@^1.1.2: inherits "^2.0.1" cross-spawn@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.0.1.tgz#a3bbb302db2297cbea3c04edf36941f4613aa399" + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" @@ -1524,8 +1524,8 @@ ejs@~0.8.3: resolved "https://registry.yarnpkg.com/ejs/-/ejs-0.8.8.tgz#ffdc56dcc35d02926dd50ad13439bbc54061d598" electron-to-chromium@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.2.3.tgz#4b4d04d237c301f72e2d15c2137b2b79f9f5ab76" + version "1.2.4" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.2.4.tgz#9751cbea89fa120bf88c226ba41eb8d0b6f1b597" elliptic@^6.0.0: version "6.4.0" @@ -1994,15 +1994,15 @@ flow-remove-types-no-whitespace@^1.0.3: babylon "^6.8.4" magic-string "^0.16.0" -for-in@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" +for-in@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.1.tgz#d6c3e3798ceaaa301047b109dedf1b1ae37a0efa" for-own@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072" + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" dependencies: - for-in "^0.1.5" + for-in "^1.0.1" foreach@^2.0.5: version "2.0.5" @@ -2493,8 +2493,8 @@ is-glob@^2.0.0, is-glob@^2.0.1: is-extglob "^1.0.0" is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: - version "2.15.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" + version "2.16.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" dependencies: generate-function "^2.0.0" generate-object-property "^1.1.0" @@ -3472,8 +3472,8 @@ postcss-discard-comments@^2.0.4: postcss "^5.0.14" postcss-discard-duplicates@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.0.2.tgz#02be520e91571ffb10738766a981d5770989bb32" + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" dependencies: postcss "^5.0.4" @@ -4088,8 +4088,8 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" resolve@^1.1.6, resolve@^1.1.7: - version "1.3.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.1.tgz#5d0a1632609b6b00a22284293db1d5d973676314" + version "1.3.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" dependencies: path-parse "^1.0.5" @@ -4717,12 +4717,12 @@ vm-browserify@0.0.4: indexof "0.0.1" vue-hot-reload-api@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.0.10.tgz#28a12ef10511e70c90f260b0cbc4066b050e8af8" + version "2.0.11" + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.0.11.tgz#bf26374fb73366ce03f799e65ef5dfd0e28a1568" vue-loader@^11.0.0: - version "11.1.2" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-11.1.2.tgz#ad2d349a7037cce9895e2358747c78290200e881" + version "11.1.3" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-11.1.3.tgz#8ed9299fba57cdd21595df4ebc74f55518d2574e" dependencies: consolidate "^0.14.0" hash-sum "^1.0.2" @@ -4738,26 +4738,26 @@ vue-loader@^11.0.0: vue-template-es2015-compiler "^1.2.2" vue-style-loader@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-2.0.1.tgz#3ec086e900f9a44086b639749dd40bc84673c3cd" + version "2.0.3" + resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-2.0.3.tgz#b464ffb6279702d4137a80ac81b5c12ac440f0a0" dependencies: hash-sum "^1.0.2" loader-utils "^1.0.2" vue-template-compiler@^2.1.0: - version "2.1.10" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.1.10.tgz#cb89643adc395e97435585522e43d0a9b1913257" + version "2.2.1" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.2.1.tgz#ca5e43db50dc6e761e3c1296313de33091783511" dependencies: de-indent "^1.0.2" he "^1.1.0" vue-template-es2015-compiler@^1.2.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.0.tgz#e4f672ab1718a3abf9171a080daefac31be117e1" + version "1.5.1" + resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.1.tgz#0c36cc57aa3a9ec13e846342cb14a72fcac8bd93" vue@^2.1.0: - version "2.1.10" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.1.10.tgz#c9235ca48c7925137be5807832ac4e3ac180427b" + version "2.2.1" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.2.1.tgz#ddbfd2f0caf38f374f5a36eea2e1edf25225b68e" watchpack@^1.2.0: version "1.3.1"