From 651184cb02010c557f839ed751f90d7c000261bc Mon Sep 17 00:00:00 2001 From: crossjs Date: Fri, 11 Nov 2016 00:17:14 +0800 Subject: [PATCH 01/12] use push instead of replace in ensureURL --- src/history/hash.js | 2 +- src/history/html5.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/history/hash.js b/src/history/hash.js index 137efe293..5bd78d6f1 100644 --- a/src/history/hash.js +++ b/src/history/hash.js @@ -54,7 +54,7 @@ export class HashHistory extends History { ensureURL () { if (getHash() !== this.current.fullPath) { - replaceHash(this.current.fullPath) + pushHash(this.current.fullPath) } } } diff --git a/src/history/html5.js b/src/history/html5.js index d0ef0603b..5cbf512ce 100644 --- a/src/history/html5.js +++ b/src/history/html5.js @@ -59,7 +59,7 @@ export class HTML5History extends History { ensureURL () { if (getLocation(this.base) !== this.current.fullPath) { - replaceState(cleanPath(this.base + this.current.fullPath)) + pushState(cleanPath(this.base + this.current.fullPath)) } } From 7237044607c057c61f70f692a5fac67ff26e8c9d Mon Sep 17 00:00:00 2001 From: crossjs Date: Mon, 14 Nov 2016 13:31:43 +0800 Subject: [PATCH 02/12] add parameter push to ensureURL, for next(false) --- src/history/base.js | 4 ++-- src/history/hash.js | 7 ++++--- src/history/html5.js | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index b8fba0d63..8bdb2915e 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -18,7 +18,7 @@ export class History { go: (n: number) => void; push: (loc: RawLocation) => void; replace: (loc: RawLocation) => void; - ensureURL: () => void; + ensureURL: (push?: boolean) => void; constructor (router: VueRouter, base: ?string) { this.router = router @@ -70,7 +70,7 @@ export class History { hook(route, current, (to: any) => { if (to === false) { // next(false) -> abort navigation, ensure current URL - this.ensureURL() + this.ensureURL(true) } else if (typeof to === 'string' || typeof to === 'object') { // next('/') or next({ path: '/' }) -> redirect this.push(to) diff --git a/src/history/hash.js b/src/history/hash.js index 5bd78d6f1..6c723dea3 100644 --- a/src/history/hash.js +++ b/src/history/hash.js @@ -52,9 +52,10 @@ export class HashHistory extends History { window.history.go(n) } - ensureURL () { - if (getHash() !== this.current.fullPath) { - pushHash(this.current.fullPath) + ensureURL (push?: boolean) { + const current = this.current.fullPath + if (getHash() !== current) { + push ? pushHash(current) : replaceHash(current) } } } diff --git a/src/history/html5.js b/src/history/html5.js index 5cbf512ce..b35414de5 100644 --- a/src/history/html5.js +++ b/src/history/html5.js @@ -57,9 +57,10 @@ export class HTML5History extends History { }) } - ensureURL () { + ensureURL (push?: boolean) { if (getLocation(this.base) !== this.current.fullPath) { - pushState(cleanPath(this.base + this.current.fullPath)) + const current = cleanPath(this.base + this.current.fullPath) + push ? pushState(current) : replaceState(current) } } From d2dc038edf01fd523f9e245d6166676c5e3f957a Mon Sep 17 00:00:00 2001 From: Wesley Mao Date: Fri, 28 Oct 2016 19:01:55 -0400 Subject: [PATCH 03/12] Allow route to use current params to fill ones it does not provide --- src/components/link.js | 2 +- src/create-matcher.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/link.js b/src/components/link.js index 8a7122b93..ca4b1057a 100644 --- a/src/components/link.js +++ b/src/components/link.js @@ -28,7 +28,7 @@ export default { const router = this.$router const current = this.$route const to = normalizeLocation(this.to, current, this.append) - const resolved = router.match(to) + const resolved = router.match(to, current) const fullPath = resolved.redirectedFrom || resolved.fullPath const base = router.history.base const href = createHref(base, fullPath, router.mode) diff --git a/src/create-matcher.js b/src/create-matcher.js index ff6b904a4..1850c5284 100644 --- a/src/create-matcher.js +++ b/src/create-matcher.js @@ -31,6 +31,19 @@ export function createMatcher (routes: Array): Matcher { if (name) { const record = nameMap[name] + + if (typeof location.params !== 'object') { + location.params = {} + } + + if (currentRoute && typeof currentRoute.params === 'object') { + for (const key in currentRoute.params) { + if (!(key in location.params)) { + location.params[key] = currentRoute.params[key] + } + } + } + if (record) { location.path = fillParams(record.path, location.params, `named route "${name}"`) return _createRoute(record, location, redirectedFrom) From 15a42044ba37ff6f61ca2b776aa24f3c7378ec73 Mon Sep 17 00:00:00 2001 From: Wesley Mao Date: Fri, 28 Oct 2016 19:59:16 -0400 Subject: [PATCH 04/12] Add tests for named children routes using parent params --- examples/nested-routes/app.js | 20 +++++++++++++++++++- test/e2e/specs/nested-routes.js | 13 ++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/examples/nested-routes/app.js b/examples/nested-routes/app.js index fd26f68ea..6e8ba8689 100644 --- a/examples/nested-routes/app.js +++ b/examples/nested-routes/app.js @@ -19,6 +19,17 @@ const Foo = { template: '
foo
' } const Bar = { template: '
bar
' } const Baz = { template: '
baz
' } +const Qux = { + template: ` +
+

qux

+ /quux + +
+ ` +} +const Quux = { template: '
quux
' } + const router = new VueRouter({ mode: 'history', base: __dirname, @@ -40,7 +51,13 @@ const router = new VueRouter({ // this allows you to leverage the component nesting without being // limited to the nested URL. // components rendered at /baz: Root -> Parent -> Baz - { path: '/baz', component: Baz } + { path: '/baz', component: Baz }, + + { + path: 'qux/:quxId', + component: Qux, + children: [{ path: 'quux', name: 'quux', component: Quux }] + } ] } ] @@ -56,6 +73,7 @@ new Vue({
  • /parent/foo
  • /parent/bar
  • /baz
  • +
  • /parent/qux
  • diff --git a/test/e2e/specs/nested-routes.js b/test/e2e/specs/nested-routes.js index 1284ebab7..41aecaa2d 100644 --- a/test/e2e/specs/nested-routes.js +++ b/test/e2e/specs/nested-routes.js @@ -3,7 +3,7 @@ module.exports = { browser .url('http://localhost:8080/nested-routes/') .waitForElementVisible('#app', 1000) - .assert.count('li a', 4) + .assert.count('li a', 5) .assert.urlEquals('http://localhost:8080/nested-routes/parent') .assert.containsText('.view', 'Parent') .assert.containsText('.view', 'default') @@ -23,6 +23,17 @@ module.exports = { .assert.containsText('.view', 'Parent') .assert.containsText('.view', 'baz') + .click('li:nth-child(5) a') + .assert.urlEquals('http://localhost:8080/nested-routes/parent/qux/123') + .assert.containsText('.view', 'Parent') + .assert.containsText('.view', 'qux') + + .click('.nested-parent a') + .assert.urlEquals('http://localhost:8080/nested-routes/parent/qux/123/quux') + .assert.containsText('.view', 'Parent') + .assert.containsText('.view', 'qux') + .assert.containsText('.view', 'quux') + // check initial visit .url('http://localhost:8080/nested-routes/parent/foo') .waitForElementVisible('#app', 1000) From 6cb12b6525981b140cb10d0720582446f4417a9e Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 14 Nov 2016 13:54:36 -0500 Subject: [PATCH 05/12] warn duplicate named routes (close #828) --- src/create-route-map.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/create-route-map.js b/src/create-route-map.js index 7911e0258..40cc3b907 100644 --- a/src/create-route-map.js +++ b/src/create-route-map.js @@ -70,7 +70,13 @@ function addRouteRecord ( } pathMap[record.path] = record - if (name) nameMap[name] = record + if (name) { + if (!nameMap[name]) { + nameMap[name] = record + } else { + warn(false, `Duplicate named routes definition: { name: "${name}", path: "${record.path}" }`) + } + } } function normalizePath (path: string, parent?: RouteRecord): string { From b007ec5a01399c31f07a37fe453f620afef3e44d Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 14 Nov 2016 14:16:20 -0500 Subject: [PATCH 06/12] [build] 2.0.2 --- dist/vue-router.js | 287 +++++++++++++++++++++++++++-------------- dist/vue-router.min.js | 4 +- 2 files changed, 189 insertions(+), 102 deletions(-) diff --git a/dist/vue-router.js b/dist/vue-router.js index 28676ad89..44a84f3cb 100644 --- a/dist/vue-router.js +++ b/dist/vue-router.js @@ -1,5 +1,5 @@ /** - * vue-router v2.0.1 + * vue-router v2.0.2 * (c) 2016 Evan You * @license MIT */ @@ -57,6 +57,9 @@ var View = { hooks.init = function (vnode) { matched.instances[name] = vnode.child } + hooks.prepatch = function (oldVnode, vnode) { + matched.instances[name] = vnode.child + } hooks.destroy = function (vnode) { if (matched.instances[name] === vnode.child) { matched.instances[name] = undefined @@ -183,7 +186,7 @@ function resolveQuery ( } function parseQuery (query) { - var res = Object.create(null) + var res = {} query = query.trim().replace(/^(\?|#|&)/, '') @@ -325,7 +328,7 @@ function isObjectEqual (a, b) { function isIncludedRoute (current, target) { return ( - current.path.indexOf(target.path) === 0 && + current.path.indexOf(target.path.replace(/\/$/, '')) === 0 && (!target.hash || current.hash === target.hash) && queryIncludes(current.query, target.query) ) @@ -398,10 +401,10 @@ var Link = { var router = this.$router var current = this.$route var to = normalizeLocation(this.to, current, this.append) - var resolved = router.match(to) + var resolved = router.match(to, current) var fullPath = resolved.redirectedFrom || resolved.fullPath var base = router.history.base - var href = base ? cleanPath(base + fullPath) : fullPath + var href = createHref(base, fullPath, router.mode) var classes = {} var activeClass = this.activeClass || router.options.linkActiveClass || 'router-link-active' var compareTarget = to.path ? createRoute(null, to) : resolved @@ -420,6 +423,11 @@ var Link = { // don't redirect on right click /* istanbul ignore if */ if (e.button !== 0) { return } + // don't redirect if `target="_blank"` + /* istanbul ignore if */ + var target = e.target.getAttribute('target') + if (/\b_blank\b/i.test(target)) { return } + e.preventDefault() if (this$1.replace) { router.replace(to) @@ -440,9 +448,12 @@ var Link = { // find the first child and apply listener and href var a = findAnchor(this.$slots.default) if (a) { - var aData = a.data || (a.data = {}) + // in case the is a static node + a.isStatic = false + var extend = _Vue.util.extend + var aData = a.data = extend({}, a.data) aData.on = on - var aAttrs = aData.attrs || (aData.attrs = {}) + var aAttrs = a.data.attrs = extend({}, a.data.attrs) aAttrs.href = href } else { // doesn't have child, apply listener to self @@ -469,10 +480,19 @@ function findAnchor (children) { } } +function createHref (base, fullPath, mode) { + var path = mode === 'hash' ? '/#' + fullPath : fullPath + return base ? cleanPath(base + path) : path +} + +var _Vue + function install (Vue) { if (install.installed) { return } install.installed = true + _Vue = Vue + Object.defineProperty(Vue.prototype, '$router', { get: function get () { return this.$root._router } }) @@ -493,6 +513,10 @@ function install (Vue) { Vue.component('router-view', View) Vue.component('router-link', Link) + + var strats = Vue.config.optionMergeStrategies + // use the same hook merging strategy for route hooks + strats.beforeRouteEnter = strats.beforeRouteLeave = strats.created } var __moduleExports = Array.isArray || function (arr) { @@ -531,14 +555,16 @@ var PATH_REGEXP = new RegExp([ /** * Parse a string for the raw tokens. * - * @param {string} str + * @param {string} str + * @param {Object=} options * @return {!Array} */ -function parse (str) { +function parse (str, options) { var tokens = [] var key = 0 var index = 0 var path = '' + var defaultDelimiter = options && options.delimiter || '/' var res while ((res = PATH_REGEXP.exec(str)) != null) { @@ -571,8 +597,8 @@ function parse (str) { var partial = prefix != null && next != null && next !== prefix var repeat = modifier === '+' || modifier === '*' var optional = modifier === '?' || modifier === '*' - var delimiter = res[2] || '/' - var pattern = capture || group || (asterisk ? '.*' : '[^' + delimiter + ']+?') + var delimiter = res[2] || defaultDelimiter + var pattern = capture || group tokens.push({ name: name || key++, @@ -582,7 +608,7 @@ function parse (str) { repeat: repeat, partial: partial, asterisk: !!asterisk, - pattern: escapeGroup(pattern) + pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') }) } @@ -603,10 +629,11 @@ function parse (str) { * Compile a string to a template function for the path. * * @param {string} str + * @param {Object=} options * @return {!function(Object=, Object=)} */ -function compile (str) { - return tokensToFunction(parse(str)) +function compile (str, options) { + return tokensToFunction(parse(str, options)) } /** @@ -817,34 +844,28 @@ function arrayToRegexp (path, keys, options) { * @return {!RegExp} */ function stringToRegexp (path, keys, options) { - var tokens = parse(path) - var re = tokensToRegExp(tokens, options) - - // Attach keys back to the regexp. - for (var i = 0; i < tokens.length; i++) { - if (typeof tokens[i] !== 'string') { - keys.push(tokens[i]) - } - } - - return attachKeys(re, keys) + return tokensToRegExp(parse(path, options), keys, options) } /** * Expose a function for taking tokens and returning a RegExp. * - * @param {!Array} tokens - * @param {Object=} options + * @param {!Array} tokens + * @param {(Array|Object)=} keys + * @param {Object=} options * @return {!RegExp} */ -function tokensToRegExp (tokens, options) { +function tokensToRegExp (tokens, keys, options) { + if (!isarray(keys)) { + options = /** @type {!Object} */ (keys || options) + keys = [] + } + options = options || {} var strict = options.strict var end = options.end !== false var route = '' - var lastToken = tokens[tokens.length - 1] - var endsWithSlash = typeof lastToken === 'string' && /\/$/.test(lastToken) // Iterate over the tokens and create our regexp string. for (var i = 0; i < tokens.length; i++) { @@ -856,6 +877,8 @@ function tokensToRegExp (tokens, options) { var prefix = escapeString(token.prefix) var capture = '(?:' + token.pattern + ')' + keys.push(token) + if (token.repeat) { capture += '(?:' + prefix + capture + ')*' } @@ -874,12 +897,15 @@ function tokensToRegExp (tokens, options) { } } + var delimiter = escapeString(options.delimiter || '/') + var endsWithDelimiter = route.slice(-delimiter.length) === delimiter + // In non-strict mode we allow a slash at the end of match. If the path to // match already ends with a slash, we remove it for consistency. The slash // is valid at the end of a path match, not in the middle. This is important // in non-ending mode, where "/test/" shouldn't match "/test//route". if (!strict) { - route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?' + route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?' } if (end) { @@ -887,10 +913,10 @@ function tokensToRegExp (tokens, options) { } else { // In non-ending mode, we need the capturing groups to match as much as // possible by using a positive lookahead to the end or next path segment. - route += strict && endsWithSlash ? '' : '(?=\\/|$)' + route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)' } - return new RegExp('^' + route, flags(options)) + return attachKeys(new RegExp('^' + route, flags(options)), keys) } /** @@ -906,15 +932,13 @@ function tokensToRegExp (tokens, options) { * @return {!RegExp} */ function pathToRegexp (path, keys, options) { - keys = keys || [] - if (!isarray(keys)) { - options = /** @type {!Object} */ (keys) + options = /** @type {!Object} */ (keys || options) keys = [] - } else if (!options) { - options = {} } + options = options || {} + if (path instanceof RegExp) { return regexpToRegexp(path, /** @type {!Array} */ (keys)) } @@ -980,7 +1004,7 @@ function addRouteRecord ( }) } - if (route.alias) { + if (route.alias !== undefined) { if (Array.isArray(route.alias)) { route.alias.forEach(function (alias) { addRouteRecord(pathMap, nameMap, { path: alias }, parent, record.path) @@ -991,7 +1015,13 @@ function addRouteRecord ( } pathMap[record.path] = record - if (name) { nameMap[name] = record } + if (name) { + if (!nameMap[name]) { + nameMap[name] = record + } else { + warn(false, ("Duplicate named routes definition: { name: \"" + name + "\", path: \"" + (record.path) + "\" }")) + } + } } function normalizePath (path, parent) { @@ -1022,6 +1052,19 @@ function createMatcher (routes) { if (name) { var record = nameMap[name] + + if (typeof location.params !== 'object') { + location.params = {} + } + + if (currentRoute && typeof currentRoute.params === 'object') { + for (var key in currentRoute.params) { + if (!(key in location.params)) { + location.params[key] = currentRoute.params[key] + } + } + } + if (record) { location.path = fillParams(record.path, location.params, ("named route \"" + name + "\"")) return _createRoute(record, location, redirectedFrom) @@ -1277,7 +1320,7 @@ History.prototype.confirmTransition = function confirmTransition (route, cb) { hook(route, current, function (to) { if (to === false) { // next(false) -> abort navigation, ensure current URL - this$1.ensureURL() + this$1.ensureURL(true) } else if (typeof to === 'string' || typeof to === 'object') { // next('/') or next({ path: '/' }) -> redirect this$1.push(to) @@ -1351,15 +1394,35 @@ function resolveQueue ( } } +function extractGuard ( + def, + key +) { + if (typeof def !== 'function') { + // extend now so that global mixins are applied. + def = _Vue.extend(def) + } + return def.options[key] +} + function extractLeaveGuards (matched) { - return flatMapComponents(matched, function (def, instance) { - var guard = def && def.beforeRouteLeave + return flatten(flatMapComponents(matched, function (def, instance) { + var guard = extractGuard(def, 'beforeRouteLeave') if (guard) { - return function routeLeaveGuard () { - return guard.apply(instance, arguments) - } + return Array.isArray(guard) + ? guard.map(function (guard) { return wrapLeaveGuard(guard, instance); }) + : wrapLeaveGuard(guard, instance) } - }).reverse() + }).reverse()) +} + +function wrapLeaveGuard ( + guard, + instance +) { + return function routeLeaveGuard () { + return guard.apply(instance, arguments) + } } function extractEnterGuards ( @@ -1367,29 +1430,46 @@ function extractEnterGuards ( cbs, isValid ) { - return flatMapComponents(matched, function (def, _, match, key) { - var guard = def && def.beforeRouteEnter + return flatten(flatMapComponents(matched, function (def, _, match, key) { + var guard = extractGuard(def, 'beforeRouteEnter') if (guard) { - return function routeEnterGuard (to, from, next) { - return guard(to, from, function (cb) { - next(cb) - if (typeof cb === 'function') { - cbs.push(function () { - // #750 - // if a router-view is wrapped with an out-in transition, - // the instance may not have been registered at this time. - // we will need to poll for registration until current route - // is no longer valid. - poll(cb, match.instances, key, isValid) - }) - } + return Array.isArray(guard) + ? guard.map(function (guard) { return wrapEnterGuard(guard, cbs, match, key, isValid); }) + : wrapEnterGuard(guard, cbs, match, key, isValid) + } + })) +} + +function wrapEnterGuard ( + guard, + cbs, + match, + key, + isValid +) { + return function routeEnterGuard (to, from, next) { + return guard(to, from, function (cb) { + next(cb) + if (typeof cb === 'function') { + cbs.push(function () { + // #750 + // if a router-view is wrapped with an out-in transition, + // the instance may not have been registered at this time. + // we will need to poll for registration until current route + // is no longer valid. + poll(cb, match.instances, key, isValid) }) } - } - }) + }) + } } -function poll (cb, instances, key, isValid) { +function poll ( + cb, // somehow flow cannot infer this is a function + instances, + key, + isValid +) { if (instances[key]) { cb(instances[key]) } else if (isValid()) { @@ -1431,7 +1511,7 @@ function flatMapComponents ( matched, fn ) { - return Array.prototype.concat.apply([], matched.map(function (m) { + return flatten(matched.map(function (m) { return Object.keys(m.components).map(function (key) { return fn( m.components[key], m.instances[key], @@ -1440,19 +1520,25 @@ function flatMapComponents ( })) } +function flatten (arr) { + return Array.prototype.concat.apply([], arr) +} + /* */ +var positionStore = Object.create(null) + function saveScrollPosition (key) { if (!key) { return } - window.sessionStorage.setItem(key, JSON.stringify({ + positionStore[key] = { x: window.pageXOffset, y: window.pageYOffset - })) + } } function getScrollPosition (key) { if (!key) { return } - return JSON.parse(window.sessionStorage.getItem(key)) + return positionStore[key] } function getElementPosition (el) { @@ -1491,8 +1577,6 @@ var HTML5History = (function (History) { History.call(this, router, base) - this.transitionTo(getLocation(this.base)) - var expectScroll = router.options.scrollBehavior window.addEventListener('popstate', function (e) { _key = e.state && e.state.key @@ -1539,9 +1623,10 @@ var HTML5History = (function (History) { }) }; - HTML5History.prototype.ensureURL = function ensureURL () { + HTML5History.prototype.ensureURL = function ensureURL (push) { if (getLocation(this.base) !== this.current.fullPath) { - replaceState(cleanPath(this.base + this.current.fullPath)) + var current = cleanPath(this.base + this.current.fullPath) + push ? pushState(current) : replaceState(current) } }; @@ -1619,8 +1704,6 @@ function replaceState (url) { var HashHistory = (function (History) { function HashHistory (router, base, fallback) { - var this$1 = this; - History.call(this, router, base) // check history fallback deeplinking @@ -1629,11 +1712,6 @@ var HashHistory = (function (History) { } ensureSlash() - this.transitionTo(getHash(), function () { - window.addEventListener('hashchange', function () { - this$1.onHashChange() - }) - }) } if ( History ) HashHistory.__proto__ = History; @@ -1675,9 +1753,10 @@ var HashHistory = (function (History) { window.history.go(n) }; - HashHistory.prototype.ensureURL = function ensureURL () { - if (getHash() !== this.current.fullPath) { - replaceHash(this.current.fullPath) + HashHistory.prototype.ensureURL = function ensureURL (push) { + var current = this.current.fullPath + if (getHash() !== current) { + push ? pushHash(current) : replaceHash(current) } }; @@ -1784,6 +1863,20 @@ var VueRouter = function VueRouter (options) { mode = 'abstract' } this.mode = mode + + switch (mode) { + case 'history': + this.history = new HTML5History(this, options.base) + break + case 'hash': + this.history = new HashHistory(this, options.base, this.fallback) + break + case 'abstract': + this.history = new AbstractHistory(this) + break + default: + assert(false, ("invalid mode: " + mode)) + } }; var prototypeAccessors = { currentRoute: {} }; @@ -1803,25 +1896,19 @@ VueRouter.prototype.init = function init (app /* Vue component instance */) { this.app = app - var ref = this; - var mode = ref.mode; - var options = ref.options; - var fallback = ref.fallback; - switch (mode) { - case 'history': - this.history = new HTML5History(this, options.base) - break - case 'hash': - this.history = new HashHistory(this, options.base, fallback) - break - case 'abstract': - this.history = new AbstractHistory(this) - break - default: - assert(false, ("invalid mode: " + mode)) + var history = this.history + + if (history instanceof HTML5History) { + history.transitionTo(getLocation(history.base)) + } else if (history instanceof HashHistory) { + history.transitionTo(getHash(), function () { + window.addEventListener('hashchange', function () { + history.onHashChange() + }) + }) } - this.history.listen(function (route) { + history.listen(function (route) { this$1.app._route = route }) }; diff --git a/dist/vue-router.min.js b/dist/vue-router.min.js index 387af6786..c3b11b633 100644 --- a/dist/vue-router.min.js +++ b/dist/vue-router.min.js @@ -1,6 +1,6 @@ /** - * vue-router v2.0.1 + * vue-router v2.0.2 * (c) 2016 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,n){if("/"===t.charAt(0))return t;if("?"===t.charAt(0)||"#"===t.charAt(0))return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var o=t.replace(/^\//,"").split("/"),i=0;i=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 n(t){return t.replace(/\/\//g,"/")}function r(t,e){if(!t)throw new Error("[vue-router] "+e)}function o(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function i(t,e){if(void 0===e&&(e={}),t){var n;try{n=a(t)}catch(t){o(!1,t.message),n={}}for(var r in e)n[r]=e[r];return n}return e}function a(t){var e=Object.create(null);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 u(t){var e=t?Object.keys(t).sort().map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return ut(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(ut(e)):r.push(ut(e)+"="+ut(t)))}),r.join("&")}return ut(e)+"="+ut(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function c(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:p(e),matched:t?s(t):[]};return n&&(r.redirectedFrom=p(n)),Object.freeze(r)}function s(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function p(t){var e=t.path,n=t.query;void 0===n&&(n={});var r=t.hash;return void 0===r&&(r=""),(e||"/")+u(n)+r}function f(t,e){return e===st?t===e:!!e&&(t.path&&e.path?t.path.replace(pt,"")===e.path.replace(pt,"")&&t.hash===e.hash&&h(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&h(t.query,e.query)&&h(t.params,e.params)))}function h(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 l(t,e){return 0===t.path.indexOf(e.path)&&(!e.hash||t.hash===e.hash)&&d(t.query,e.query)}function d(t,e){for(var n in e)if(!(n in t))return!1;return!0}function y(n,r,o){var a="string"==typeof n?{path:n}:n;if(a.name||a._normalized)return a;var u=e(a.path||""),c=r&&r.path||"/",s=u.path?t(u.path,c,o):r&&r.path||"/",p=i(u.query,a.query),f=a.hash||u.hash;return f&&"#"!==f.charAt(0)&&(f="#"+f),{_normalized:!0,path:s,query:p,hash:f}}function v(t){if(t)for(var e,n=0;n=t.length?n():t[o]?e(t[o],function(){r(o+1)}):r(o+1)};r(0)}function I(t){if(!t)if(Ot){var e=document.querySelector("base");t=e?e.getAttribute("href"):"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function M(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}var at={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,o=e.parent,i=e.data;i.routerView=!0;for(var a=o.$route,u=o._routerViewCache||(o._routerViewCache={}),c=0,s=!1;o;)o.$vnode&&o.$vnode.data.routerView&&c++,o._inactive&&(s=!0),o=o.$parent;i.routerViewDepth=c;var p=a.matched[c];if(!p)return t();var f=n.name,h=s?u[f]:u[f]=p.components[f];if(!s){var l=i.hook||(i.hook={});l.init=function(t){p.instances[f]=t.child},l.destroy=function(t){p.instances[f]===t.child&&(p.instances[f]=void 0)}}return t(h,i,r)}},ut=encodeURIComponent,ct=decodeURIComponent,st=c(null,{path:"/"}),pt=/\/$/,ft=[String,Object],ht={name:"router-link",props:{to:{type:ft,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String},render:function(t){var e=this,r=this.$router,o=this.$route,i=y(this.to,o,this.append),a=r.match(i),u=a.redirectedFrom||a.fullPath,s=r.history.base,p=s?n(s+u):u,h={},d=this.activeClass||r.options.linkActiveClass||"router-link-active",m=i.path?c(null,i):a;h[d]=this.exact?f(o,m):l(o,m);var g={click:function(t){t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||0===t.button&&(t.preventDefault(),e.replace?r.replace(i):r.push(i))}},w={class:h};if("a"===this.tag)w.on=g,w.attrs={href:p};else{var b=v(this.$slots.default);if(b){var x=b.data||(b.data={});x.on=g;var k=x.attrs||(x.attrs={});k.href=p}else w.on=g}return t(this.tag,w,this.$slots.default)}},lt=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},dt=lt,yt=T,vt=g,mt=w,gt=k,wt=_,bt=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");yt.parse=vt,yt.compile=mt,yt.tokensToFunction=gt,yt.tokensToRegExp=wt;var xt=Object.create(null),kt=Object.create(null),Ot="undefined"!=typeof window,Et=Ot&&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)}(),Rt=function(t,e){this.router=t,this.base=I(e),this.current=st,this.pending=null};Rt.prototype.listen=function(t){this.cb=t},Rt.prototype.transitionTo=function(t,e){var n=this,r=this.router.match(t,this.current);this.confirmTransition(r,function(){n.updateRoute(r),e&&e(r),n.ensureURL()})},Rt.prototype.confirmTransition=function(t,e){var n=this,r=this.current;if(f(t,r))return void this.ensureURL();var o=M(this.current.matched,t.matched),i=o.deactivated,a=o.activated,u=[].concat(z(i),this.router.beforeHooks,a.map(function(t){return t.beforeEnter}),N(a));this.pending=t;var c=function(e,o){n.pending===t&&e(t,r,function(t){t===!1?n.ensureURL():"string"==typeof t||"object"==typeof t?n.push(t):o(t)})};H(u,c,function(){var r=[],o=F(a,r,function(){return n.current===t});H(o,c,function(){n.pending===t&&(n.pending=null,e(t),n.router.app.$nextTick(function(){r.forEach(function(t){return t()})}))})})},Rt.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 jt=function(){return String(Date.now())},St=jt(),$t=function(t){function e(e,n){var r=this;t.call(this,e,n),this.transitionTo(Z(this.base));var o=e.options.scrollBehavior;window.addEventListener("popstate",function(t){St=t.state&&t.state.key;var e=r.current;r.transitionTo(Z(r.base),function(t){o&&r.handleScroll(t,e,!0)})}),o&&window.addEventListener("scroll",function(){K(St)})}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){var e=this,r=this.current;this.transitionTo(t,function(t){tt(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.replace=function(t){var e=this,r=this.current;this.transitionTo(t,function(t){et(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.ensureURL=function(){Z(this.base)!==this.current.fullPath&&et(n(this.base+this.current.fullPath))},e.prototype.handleScroll=function(t,e,n){var o=this.router;if(o.app){var i=o.options.scrollBehavior;i&&(r("function"==typeof i,"scrollBehavior must be a function"),o.app.$nextTick(function(){var r=X(St),o=i(t,e,n?r:null);if(o){var a="object"==typeof o;if(a&&"string"==typeof o.selector){var u=document.querySelector(o.selector);u?r=Y(u):W(o)&&(r=G(o))}else a&&W(o)&&(r=G(o));r&&window.scrollTo(r.x,r.y)}}))}},e}(Rt),At=function(t){function e(e,n,r){var o=this;t.call(this,e,n),r&&this.checkFallback()||(nt(),this.transitionTo(rt(),function(){window.addEventListener("hashchange",function(){o.onHashChange()})}))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.checkFallback=function(){var t=Z(this.base);if(!/^\/#/.test(t))return window.location.replace(n(this.base+"/#"+t)),!0},e.prototype.onHashChange=function(){nt()&&this.transitionTo(rt(),function(t){it(t.fullPath)})},e.prototype.push=function(t){this.transitionTo(t,function(t){ot(t.fullPath)})},e.prototype.replace=function(t){this.transitionTo(t,function(t){it(t.fullPath)})},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(){rt()!==this.current.fullPath&&it(this.current.fullPath)},e}(Rt),_t=function(t){function e(e){t.call(this,e),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){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index+1).concat(t),e.index++})},e.prototype.replace=function(t){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index).concat(t)})},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.ensureURL=function(){},e}(Rt),Tt=function(t){void 0===t&&(t={}),this.app=null,this.options=t,this.beforeHooks=[],this.afterHooks=[],this.match=U(t.routes||[]);var e=t.mode||"hash";this.fallback="history"===e&&!Et,this.fallback&&(e="hash"),Ot||(e="abstract"),this.mode=e},qt={currentRoute:{}};return qt.currentRoute.get=function(){return this.history&&this.history.current},Tt.prototype.init=function(t){var e=this;r(m.installed,"not installed. Make sure to call `Vue.use(VueRouter)` before creating root instance."),this.app=t;var n=this,o=n.mode,i=n.options,a=n.fallback;switch(o){case"history":this.history=new $t(this,i.base);break;case"hash":this.history=new At(this,i.base,a);break;case"abstract":this.history=new _t(this);break;default:r(!1,"invalid mode: "+o)}this.history.listen(function(t){e.app._route=t})},Tt.prototype.beforeEach=function(t){this.beforeHooks.push(t)},Tt.prototype.afterEach=function(t){this.afterHooks.push(t)},Tt.prototype.push=function(t){this.history.push(t)},Tt.prototype.replace=function(t){this.history.replace(t)},Tt.prototype.go=function(t){this.history.go(t)},Tt.prototype.back=function(){this.go(-1)},Tt.prototype.forward=function(){this.go(1)},Tt.prototype.getMatchedComponents=function(){return this.currentRoute?[].concat.apply([],this.currentRoute.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},Object.defineProperties(Tt.prototype,qt),Tt.install=m,Ot&&window.Vue&&window.Vue.use(Tt),Tt}); \ 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,n){if("/"===t.charAt(0))return t;if("?"===t.charAt(0)||"#"===t.charAt(0))return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var o=t.replace(/^\//,"").split("/"),i=0;i=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 n(t){return t.replace(/\/\//g,"/")}function r(t,e){if(!t)throw new Error("[vue-router] "+e)}function o(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function i(t,e){if(void 0===e&&(e={}),t){var n;try{n=a(t)}catch(t){o(!1,t.message),n={}}for(var r in e)n[r]=e[r];return n}return e}function a(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=dt(n.shift()),o=n.length>0?dt(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 u(t){var e=t?Object.keys(t).sort().map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return lt(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(lt(e)):r.push(lt(e)+"="+lt(t)))}),r.join("&")}return lt(e)+"="+lt(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function c(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:f(e),matched:t?s(t):[]};return n&&(r.redirectedFrom=f(n)),Object.freeze(r)}function s(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function f(t){var e=t.path,n=t.query;void 0===n&&(n={});var r=t.hash;return void 0===r&&(r=""),(e||"/")+u(n)+r}function p(t,e){return e===yt?t===e:!!e&&(t.path&&e.path?t.path.replace(vt,"")===e.path.replace(vt,"")&&t.hash===e.hash&&h(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&h(t.query,e.query)&&h(t.params,e.params)))}function h(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 l(t,e){return 0===t.path.indexOf(e.path.replace(/\/$/,""))&&(!e.hash||t.hash===e.hash)&&d(t.query,e.query)}function d(t,e){for(var n in e)if(!(n in t))return!1;return!0}function y(n,r,o){var a="string"==typeof n?{path:n}:n;if(a.name||a._normalized)return a;var u=e(a.path||""),c=r&&r.path||"/",s=u.path?t(u.path,c,o):r&&r.path||"/",f=i(u.query,a.query),p=a.hash||u.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:s,query:f,hash:p}}function v(t){if(t)for(var e,n=0;n=t.length?n():t[o]?e(t[o],function(){r(o+1)}):r(o+1)};r(0)}function z(t){if(!t)if(_t){var e=document.querySelector("base");t=e?e.getAttribute("href"):"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function F(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}var pt,ht={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,o=e.parent,i=e.data;i.routerView=!0;for(var a=o.$route,u=o._routerViewCache||(o._routerViewCache={}),c=0,s=!1;o;)o.$vnode&&o.$vnode.data.routerView&&c++,o._inactive&&(s=!0),o=o.$parent;i.routerViewDepth=c;var f=a.matched[c];if(!f)return t();var p=n.name,h=s?u[p]:u[p]=f.components[p];if(!s){var l=i.hook||(i.hook={});l.init=function(t){f.instances[p]=t.child},l.prepatch=function(t,e){f.instances[p]=e.child},l.destroy=function(t){f.instances[p]===t.child&&(f.instances[p]=void 0)}}return t(h,i,r)}},lt=encodeURIComponent,dt=decodeURIComponent,yt=c(null,{path:"/"}),vt=/\/$/,mt=[String,Object],gt={name:"router-link",props:{to:{type:mt,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String},render:function(t){var e=this,n=this.$router,r=this.$route,o=y(this.to,r,this.append),i=n.match(o,r),a=i.redirectedFrom||i.fullPath,u=n.history.base,s=m(u,a,n.mode),f={},h=this.activeClass||n.options.linkActiveClass||"router-link-active",d=o.path?c(null,o):i;f[h]=this.exact?p(r,d):l(r,d);var g={click:function(t){if(!(t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||0!==t.button)){var r=t.target.getAttribute("target");/\b_blank\b/i.test(r)||(t.preventDefault(),e.replace?n.replace(o):n.push(o))}}},w={class:f};if("a"===this.tag)w.on=g,w.attrs={href:s};else{var b=v(this.$slots.default);if(b){b.isStatic=!1;var x=pt.util.extend,k=b.data=x({},b.data);k.on=g;var O=b.data.attrs=x({},b.data.attrs);O.href=s}else w.on=g}return t(this.tag,w,this.$slots.default)}},wt=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},bt=wt,xt=q,kt=w,Ot=b,Et=O,Rt=T,jt=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");xt.parse=kt,xt.compile=Ot,xt.tokensToFunction=Et,xt.tokensToRegExp=Rt;var At=Object.create(null),$t=Object.create(null),_t="undefined"!=typeof window,St=_t&&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)}(),Tt=function(t,e){this.router=t,this.base=z(e),this.current=yt,this.pending=null};Tt.prototype.listen=function(t){this.cb=t},Tt.prototype.transitionTo=function(t,e){var n=this,r=this.router.match(t,this.current);this.confirmTransition(r,function(){n.updateRoute(r),e&&e(r),n.ensureURL()})},Tt.prototype.confirmTransition=function(t,e){var n=this,r=this.current;if(p(t,r))return void this.ensureURL();var o=F(this.current.matched,t.matched),i=o.deactivated,a=o.activated,u=[].concat(D(i),this.router.beforeHooks,a.map(function(t){return t.beforeEnter}),Y(a));this.pending=t;var c=function(e,o){n.pending===t&&e(t,r,function(t){t===!1?n.ensureURL(!0):"string"==typeof t||"object"==typeof t?n.push(t):o(t)})};H(u,c,function(){var r=[],o=N(a,r,function(){return n.current===t});H(o,c,function(){n.pending===t&&(n.pending=null,e(t),n.router.app.$nextTick(function(){r.forEach(function(t){return t()})}))})})},Tt.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 qt=Object.create(null),Ct=function(){return String(Date.now())},Pt=Ct(),Ut=function(t){function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavior;window.addEventListener("popstate",function(t){Pt=t.state&&t.state.key;var e=r.current;r.transitionTo(ot(r.base),function(t){o&&r.handleScroll(t,e,!0)})}),o&&window.addEventListener("scroll",function(){Q(Pt)})}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){var e=this,r=this.current;this.transitionTo(t,function(t){it(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.replace=function(t){var e=this,r=this.current;this.transitionTo(t,function(t){at(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.ensureURL=function(t){if(ot(this.base)!==this.current.fullPath){var e=n(this.base+this.current.fullPath);t?it(e):at(e)}},e.prototype.handleScroll=function(t,e,n){var o=this.router;if(o.app){var i=o.options.scrollBehavior;i&&(r("function"==typeof i,"scrollBehavior must be a function"),o.app.$nextTick(function(){var r=Z(Pt),o=i(t,e,n?r:null);if(o){var a="object"==typeof o;if(a&&"string"==typeof o.selector){var u=document.querySelector(o.selector);u?r=tt(u):et(o)&&(r=nt(o))}else a&&et(o)&&(r=nt(o));r&&window.scrollTo(r.x,r.y)}}))}},e}(Tt),Lt=function(t){function e(e,n,r){t.call(this,e,n),r&&this.checkFallback()||ut()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.checkFallback=function(){var t=ot(this.base);if(!/^\/#/.test(t))return window.location.replace(n(this.base+"/#"+t)),!0},e.prototype.onHashChange=function(){ut()&&this.transitionTo(ct(),function(t){ft(t.fullPath)})},e.prototype.push=function(t){this.transitionTo(t,function(t){st(t.fullPath)})},e.prototype.replace=function(t){this.transitionTo(t,function(t){ft(t.fullPath)})},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;ct()!==e&&(t?st(e):ft(e))},e}(Tt),Vt=function(t){function e(e){t.call(this,e),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){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index+1).concat(t),e.index++})},e.prototype.replace=function(t){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index).concat(t)})},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.ensureURL=function(){},e}(Tt),Mt=function(t){void 0===t&&(t={}),this.app=null,this.options=t,this.beforeHooks=[],this.afterHooks=[],this.match=L(t.routes||[]);var e=t.mode||"hash";switch(this.fallback="history"===e&&!St,this.fallback&&(e="hash"),_t||(e="abstract"),this.mode=e,e){case"history":this.history=new Ut(this,t.base);break;case"hash":this.history=new Lt(this,t.base,this.fallback);break;case"abstract":this.history=new Vt(this);break;default:r(!1,"invalid mode: "+e)}},Bt={currentRoute:{}};return Bt.currentRoute.get=function(){return this.history&&this.history.current},Mt.prototype.init=function(t){var e=this;r(g.installed,"not installed. Make sure to call `Vue.use(VueRouter)` before creating root instance."),this.app=t;var n=this.history;n instanceof Ut?n.transitionTo(ot(n.base)):n instanceof Lt&&n.transitionTo(ct(),function(){window.addEventListener("hashchange",function(){n.onHashChange()})}),n.listen(function(t){e.app._route=t})},Mt.prototype.beforeEach=function(t){this.beforeHooks.push(t)},Mt.prototype.afterEach=function(t){this.afterHooks.push(t)},Mt.prototype.push=function(t){this.history.push(t)},Mt.prototype.replace=function(t){this.history.replace(t)},Mt.prototype.go=function(t){this.history.go(t)},Mt.prototype.back=function(){this.go(-1)},Mt.prototype.forward=function(){this.go(1)},Mt.prototype.getMatchedComponents=function(){return this.currentRoute?[].concat.apply([],this.currentRoute.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},Object.defineProperties(Mt.prototype,Bt),Mt.install=g,_t&&window.Vue&&window.Vue.use(Mt),Mt}); \ No newline at end of file From 4ea44bd4fc0840f829ca8510260e23504b3ec752 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 14 Nov 2016 14:16:20 -0500 Subject: [PATCH 07/12] [release] 2.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff7fa79ea..63a090a8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-router", - "version": "2.0.1", + "version": "2.0.2", "description": "Official router for Vue.js 2.0", "author": "Evan You", "license": "MIT", From b63c67d904389fca9b7699d67c3d7883e90cb21e Mon Sep 17 00:00:00 2001 From: Alec Koumjian Date: Fri, 11 Nov 2016 18:29:40 -0800 Subject: [PATCH 08/12] Router is able to recognize components by string --- docs/en/essentials/getting-started.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/en/essentials/getting-started.md b/docs/en/essentials/getting-started.md index 6ec89648d..6d319d3c3 100644 --- a/docs/en/essentials/getting-started.md +++ b/docs/en/essentials/getting-started.md @@ -40,7 +40,8 @@ const Bar = { template: '
    bar
    ' } // 2. Define some routes // Each route should map to a component. The "component" can // either be an actual component constructor created via -// Vue.extend(), or just a component options object. +// Vue.extend(), a component name created with Vue.component(), +// or just a component options object. // We'll talk about nested routes later. const routes = [ { path: '/foo', component: Foo }, From 75f90df3f7c8d6cfbfe7fd5edabfac7959a98226 Mon Sep 17 00:00:00 2001 From: Alec Koumjian Date: Mon, 14 Nov 2016 10:41:33 -0800 Subject: [PATCH 09/12] Change to recommended language --- docs/en/essentials/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/essentials/getting-started.md b/docs/en/essentials/getting-started.md index 6d319d3c3..2b09c0c59 100644 --- a/docs/en/essentials/getting-started.md +++ b/docs/en/essentials/getting-started.md @@ -40,7 +40,7 @@ const Bar = { template: '
    bar
    ' } // 2. Define some routes // Each route should map to a component. The "component" can // either be an actual component constructor created via -// Vue.extend(), a component name created with Vue.component(), +// Vue.extend(), a component id string registered via Vue.component(), // or just a component options object. // We'll talk about nested routes later. const routes = [ From 4d5d126976eeddea666ee41da030674b3d47de22 Mon Sep 17 00:00:00 2001 From: Rahul Kadyan Date: Fri, 18 Nov 2016 21:33:35 +0530 Subject: [PATCH 10/12] Remove extras from old params in named routes (#910) * :bug: Remove extra old params in named routes * :white_check_mark: Add tests --- examples/nested-routes/app.js | 13 ++++++++++++- src/create-matcher.js | 31 ++++++++++++++++++++++++------- test/e2e/specs/nested-routes.js | 13 ++++++++++++- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/examples/nested-routes/app.js b/examples/nested-routes/app.js index 6e8ba8689..9f35e3064 100644 --- a/examples/nested-routes/app.js +++ b/examples/nested-routes/app.js @@ -28,6 +28,14 @@ const Qux = { ` } +const Quy = { + template: ` +
    +

    quy

    +
    {{ JSON.stringify(Object.keys($route.params)) }}
    +
    + ` +} const Quux = { template: '
    quux
    ' } const router = new VueRouter({ @@ -57,7 +65,9 @@ const router = new VueRouter({ path: 'qux/:quxId', component: Qux, children: [{ path: 'quux', name: 'quux', component: Quux }] - } + }, + + { path: 'quy/:quyId', component: Quy } ] } ] @@ -74,6 +84,7 @@ new Vue({
  • /parent/bar
  • /baz
  • /parent/qux
  • +
  • /parent/quy
  • diff --git a/src/create-matcher.js b/src/create-matcher.js index 1850c5284..748f451e8 100644 --- a/src/create-matcher.js +++ b/src/create-matcher.js @@ -14,6 +14,10 @@ const regexpCache: { } } = Object.create(null) +const regexpParamsCache: { + [key: string]: Array +} = Object.create(null) + const regexpCompileCache: { [key: string]: Function } = Object.create(null) @@ -31,6 +35,7 @@ export function createMatcher (routes: Array): Matcher { if (name) { const record = nameMap[name] + const paramNames = getParams(record.path) if (typeof location.params !== 'object') { location.params = {} @@ -38,7 +43,7 @@ export function createMatcher (routes: Array): Matcher { if (currentRoute && typeof currentRoute.params === 'object') { for (const key in currentRoute.params) { - if (!(key in location.params)) { + if (!(key in location.params) && paramNames.indexOf(key) > -1) { location.params[key] = currentRoute.params[key] } } @@ -150,13 +155,10 @@ export function createMatcher (routes: Array): Matcher { return match } -function matchRoute ( - path: string, - params: Object, - pathname: string -): boolean { - let keys, regexp +function getRouteRegex (path: string): Object { const hit = regexpCache[path] + let keys, regexp + if (hit) { keys = hit.keys regexp = hit.regexp @@ -165,6 +167,16 @@ function matchRoute ( regexp = Regexp(path, keys) regexpCache[path] = { keys, regexp } } + + return { keys, regexp } +} + +function matchRoute ( + path: string, + params: Object, + pathname: string +): boolean { + const { regexp, keys } = getRouteRegex(path) const m = pathname.match(regexp) if (!m) { @@ -198,6 +210,11 @@ function fillParams ( } } +function getParams (path: string): Array { + return regexpParamsCache[path] || + (regexpParamsCache[path] = getRouteRegex(path).keys.map(key => key.name)) +} + function resolveRecordPath (path: string, record: RouteRecord): string { return resolvePath(path, record.parent ? record.parent.path : '/', true) } diff --git a/test/e2e/specs/nested-routes.js b/test/e2e/specs/nested-routes.js index 41aecaa2d..172ded37e 100644 --- a/test/e2e/specs/nested-routes.js +++ b/test/e2e/specs/nested-routes.js @@ -3,7 +3,7 @@ module.exports = { browser .url('http://localhost:8080/nested-routes/') .waitForElementVisible('#app', 1000) - .assert.count('li a', 5) + .assert.count('li a', 6) .assert.urlEquals('http://localhost:8080/nested-routes/parent') .assert.containsText('.view', 'Parent') .assert.containsText('.view', 'default') @@ -34,6 +34,17 @@ module.exports = { .assert.containsText('.view', 'qux') .assert.containsText('.view', 'quux') + .click('li:nth-child(6) a') + .assert.urlEquals('http://localhost:8080/nested-routes/parent/quy/123') + .assert.containsText('.view', 'Parent') + .assert.containsText('.view', 'quy') + .assert.evaluate(function () { + var params = JSON.parse(document.querySelector('pre').textContent) + return ( + JSON.stringify(params) === JSON.stringify(['quyId']) + ) + }, null, '/') + // check initial visit .url('http://localhost:8080/nested-routes/parent/foo') .waitForElementVisible('#app', 1000) From bbd0b84bbd0bb02dcd210a1b87e8d1344a7c5bed Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 18 Nov 2016 11:05:01 -0500 Subject: [PATCH 11/12] [build] 2.0.3 --- dist/vue-router.js | 33 +++++++++++++++++++++++++-------- dist/vue-router.min.js | 4 ++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/dist/vue-router.js b/dist/vue-router.js index 44a84f3cb..cb7676761 100644 --- a/dist/vue-router.js +++ b/dist/vue-router.js @@ -1,5 +1,5 @@ /** - * vue-router v2.0.2 + * vue-router v2.0.3 * (c) 2016 Evan You * @license MIT */ @@ -1035,6 +1035,8 @@ function normalizePath (path, parent) { var regexpCache = Object.create(null) +var regexpParamsCache = Object.create(null) + var regexpCompileCache = Object.create(null) function createMatcher (routes) { @@ -1052,6 +1054,7 @@ function createMatcher (routes) { if (name) { var record = nameMap[name] + var paramNames = getParams(record.path) if (typeof location.params !== 'object') { location.params = {} @@ -1059,7 +1062,7 @@ function createMatcher (routes) { if (currentRoute && typeof currentRoute.params === 'object') { for (var key in currentRoute.params) { - if (!(key in location.params)) { + if (!(key in location.params) && paramNames.indexOf(key) > -1) { location.params[key] = currentRoute.params[key] } } @@ -1174,13 +1177,10 @@ function createMatcher (routes) { return match } -function matchRoute ( - path, - params, - pathname -) { - var keys, regexp +function getRouteRegex (path) { var hit = regexpCache[path] + var keys, regexp + if (hit) { keys = hit.keys regexp = hit.regexp @@ -1189,6 +1189,18 @@ function matchRoute ( regexp = index(path, keys) regexpCache[path] = { keys: keys, regexp: regexp } } + + return { keys: keys, regexp: regexp } +} + +function matchRoute ( + path, + params, + pathname +) { + var ref = getRouteRegex(path); + var regexp = ref.regexp; + var keys = ref.keys; var m = pathname.match(regexp) if (!m) { @@ -1222,6 +1234,11 @@ function fillParams ( } } +function getParams (path) { + return regexpParamsCache[path] || + (regexpParamsCache[path] = getRouteRegex(path).keys.map(function (key) { return key.name; })) +} + function resolveRecordPath (path, record) { return resolvePath(path, record.parent ? record.parent.path : '/', true) } diff --git a/dist/vue-router.min.js b/dist/vue-router.min.js index c3b11b633..76c4a7372 100644 --- a/dist/vue-router.min.js +++ b/dist/vue-router.min.js @@ -1,6 +1,6 @@ /** - * vue-router v2.0.2 + * vue-router v2.0.3 * (c) 2016 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,n){if("/"===t.charAt(0))return t;if("?"===t.charAt(0)||"#"===t.charAt(0))return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var o=t.replace(/^\//,"").split("/"),i=0;i=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 n(t){return t.replace(/\/\//g,"/")}function r(t,e){if(!t)throw new Error("[vue-router] "+e)}function o(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function i(t,e){if(void 0===e&&(e={}),t){var n;try{n=a(t)}catch(t){o(!1,t.message),n={}}for(var r in e)n[r]=e[r];return n}return e}function a(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=dt(n.shift()),o=n.length>0?dt(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 u(t){var e=t?Object.keys(t).sort().map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return lt(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(lt(e)):r.push(lt(e)+"="+lt(t)))}),r.join("&")}return lt(e)+"="+lt(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function c(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:f(e),matched:t?s(t):[]};return n&&(r.redirectedFrom=f(n)),Object.freeze(r)}function s(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function f(t){var e=t.path,n=t.query;void 0===n&&(n={});var r=t.hash;return void 0===r&&(r=""),(e||"/")+u(n)+r}function p(t,e){return e===yt?t===e:!!e&&(t.path&&e.path?t.path.replace(vt,"")===e.path.replace(vt,"")&&t.hash===e.hash&&h(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&h(t.query,e.query)&&h(t.params,e.params)))}function h(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 l(t,e){return 0===t.path.indexOf(e.path.replace(/\/$/,""))&&(!e.hash||t.hash===e.hash)&&d(t.query,e.query)}function d(t,e){for(var n in e)if(!(n in t))return!1;return!0}function y(n,r,o){var a="string"==typeof n?{path:n}:n;if(a.name||a._normalized)return a;var u=e(a.path||""),c=r&&r.path||"/",s=u.path?t(u.path,c,o):r&&r.path||"/",f=i(u.query,a.query),p=a.hash||u.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:s,query:f,hash:p}}function v(t){if(t)for(var e,n=0;n=t.length?n():t[o]?e(t[o],function(){r(o+1)}):r(o+1)};r(0)}function z(t){if(!t)if(_t){var e=document.querySelector("base");t=e?e.getAttribute("href"):"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function F(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}var pt,ht={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,o=e.parent,i=e.data;i.routerView=!0;for(var a=o.$route,u=o._routerViewCache||(o._routerViewCache={}),c=0,s=!1;o;)o.$vnode&&o.$vnode.data.routerView&&c++,o._inactive&&(s=!0),o=o.$parent;i.routerViewDepth=c;var f=a.matched[c];if(!f)return t();var p=n.name,h=s?u[p]:u[p]=f.components[p];if(!s){var l=i.hook||(i.hook={});l.init=function(t){f.instances[p]=t.child},l.prepatch=function(t,e){f.instances[p]=e.child},l.destroy=function(t){f.instances[p]===t.child&&(f.instances[p]=void 0)}}return t(h,i,r)}},lt=encodeURIComponent,dt=decodeURIComponent,yt=c(null,{path:"/"}),vt=/\/$/,mt=[String,Object],gt={name:"router-link",props:{to:{type:mt,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String},render:function(t){var e=this,n=this.$router,r=this.$route,o=y(this.to,r,this.append),i=n.match(o,r),a=i.redirectedFrom||i.fullPath,u=n.history.base,s=m(u,a,n.mode),f={},h=this.activeClass||n.options.linkActiveClass||"router-link-active",d=o.path?c(null,o):i;f[h]=this.exact?p(r,d):l(r,d);var g={click:function(t){if(!(t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||0!==t.button)){var r=t.target.getAttribute("target");/\b_blank\b/i.test(r)||(t.preventDefault(),e.replace?n.replace(o):n.push(o))}}},w={class:f};if("a"===this.tag)w.on=g,w.attrs={href:s};else{var b=v(this.$slots.default);if(b){b.isStatic=!1;var x=pt.util.extend,k=b.data=x({},b.data);k.on=g;var O=b.data.attrs=x({},b.data.attrs);O.href=s}else w.on=g}return t(this.tag,w,this.$slots.default)}},wt=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},bt=wt,xt=q,kt=w,Ot=b,Et=O,Rt=T,jt=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");xt.parse=kt,xt.compile=Ot,xt.tokensToFunction=Et,xt.tokensToRegExp=Rt;var At=Object.create(null),$t=Object.create(null),_t="undefined"!=typeof window,St=_t&&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)}(),Tt=function(t,e){this.router=t,this.base=z(e),this.current=yt,this.pending=null};Tt.prototype.listen=function(t){this.cb=t},Tt.prototype.transitionTo=function(t,e){var n=this,r=this.router.match(t,this.current);this.confirmTransition(r,function(){n.updateRoute(r),e&&e(r),n.ensureURL()})},Tt.prototype.confirmTransition=function(t,e){var n=this,r=this.current;if(p(t,r))return void this.ensureURL();var o=F(this.current.matched,t.matched),i=o.deactivated,a=o.activated,u=[].concat(D(i),this.router.beforeHooks,a.map(function(t){return t.beforeEnter}),Y(a));this.pending=t;var c=function(e,o){n.pending===t&&e(t,r,function(t){t===!1?n.ensureURL(!0):"string"==typeof t||"object"==typeof t?n.push(t):o(t)})};H(u,c,function(){var r=[],o=N(a,r,function(){return n.current===t});H(o,c,function(){n.pending===t&&(n.pending=null,e(t),n.router.app.$nextTick(function(){r.forEach(function(t){return t()})}))})})},Tt.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 qt=Object.create(null),Ct=function(){return String(Date.now())},Pt=Ct(),Ut=function(t){function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavior;window.addEventListener("popstate",function(t){Pt=t.state&&t.state.key;var e=r.current;r.transitionTo(ot(r.base),function(t){o&&r.handleScroll(t,e,!0)})}),o&&window.addEventListener("scroll",function(){Q(Pt)})}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){var e=this,r=this.current;this.transitionTo(t,function(t){it(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.replace=function(t){var e=this,r=this.current;this.transitionTo(t,function(t){at(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.ensureURL=function(t){if(ot(this.base)!==this.current.fullPath){var e=n(this.base+this.current.fullPath);t?it(e):at(e)}},e.prototype.handleScroll=function(t,e,n){var o=this.router;if(o.app){var i=o.options.scrollBehavior;i&&(r("function"==typeof i,"scrollBehavior must be a function"),o.app.$nextTick(function(){var r=Z(Pt),o=i(t,e,n?r:null);if(o){var a="object"==typeof o;if(a&&"string"==typeof o.selector){var u=document.querySelector(o.selector);u?r=tt(u):et(o)&&(r=nt(o))}else a&&et(o)&&(r=nt(o));r&&window.scrollTo(r.x,r.y)}}))}},e}(Tt),Lt=function(t){function e(e,n,r){t.call(this,e,n),r&&this.checkFallback()||ut()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.checkFallback=function(){var t=ot(this.base);if(!/^\/#/.test(t))return window.location.replace(n(this.base+"/#"+t)),!0},e.prototype.onHashChange=function(){ut()&&this.transitionTo(ct(),function(t){ft(t.fullPath)})},e.prototype.push=function(t){this.transitionTo(t,function(t){st(t.fullPath)})},e.prototype.replace=function(t){this.transitionTo(t,function(t){ft(t.fullPath)})},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;ct()!==e&&(t?st(e):ft(e))},e}(Tt),Vt=function(t){function e(e){t.call(this,e),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){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index+1).concat(t),e.index++})},e.prototype.replace=function(t){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index).concat(t)})},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.ensureURL=function(){},e}(Tt),Mt=function(t){void 0===t&&(t={}),this.app=null,this.options=t,this.beforeHooks=[],this.afterHooks=[],this.match=L(t.routes||[]);var e=t.mode||"hash";switch(this.fallback="history"===e&&!St,this.fallback&&(e="hash"),_t||(e="abstract"),this.mode=e,e){case"history":this.history=new Ut(this,t.base);break;case"hash":this.history=new Lt(this,t.base,this.fallback);break;case"abstract":this.history=new Vt(this);break;default:r(!1,"invalid mode: "+e)}},Bt={currentRoute:{}};return Bt.currentRoute.get=function(){return this.history&&this.history.current},Mt.prototype.init=function(t){var e=this;r(g.installed,"not installed. Make sure to call `Vue.use(VueRouter)` before creating root instance."),this.app=t;var n=this.history;n instanceof Ut?n.transitionTo(ot(n.base)):n instanceof Lt&&n.transitionTo(ct(),function(){window.addEventListener("hashchange",function(){n.onHashChange()})}),n.listen(function(t){e.app._route=t})},Mt.prototype.beforeEach=function(t){this.beforeHooks.push(t)},Mt.prototype.afterEach=function(t){this.afterHooks.push(t)},Mt.prototype.push=function(t){this.history.push(t)},Mt.prototype.replace=function(t){this.history.replace(t)},Mt.prototype.go=function(t){this.history.go(t)},Mt.prototype.back=function(){this.go(-1)},Mt.prototype.forward=function(){this.go(1)},Mt.prototype.getMatchedComponents=function(){return this.currentRoute?[].concat.apply([],this.currentRoute.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},Object.defineProperties(Mt.prototype,Bt),Mt.install=g,_t&&window.Vue&&window.Vue.use(Mt),Mt}); \ 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,n){if("/"===t.charAt(0))return t;if("?"===t.charAt(0)||"#"===t.charAt(0))return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var o=t.replace(/^\//,"").split("/"),i=0;i=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 n(t){return t.replace(/\/\//g,"/")}function r(t,e){if(!t)throw new Error("[vue-router] "+e)}function o(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function i(t,e){if(void 0===e&&(e={}),t){var n;try{n=a(t)}catch(t){o(!1,t.message),n={}}for(var r in e)n[r]=e[r];return n}return e}function a(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=vt(n.shift()),o=n.length>0?vt(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 u(t){var e=t?Object.keys(t).sort().map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return yt(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(yt(e)):r.push(yt(e)+"="+yt(t)))}),r.join("&")}return yt(e)+"="+yt(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function c(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:f(e),matched:t?s(t):[]};return n&&(r.redirectedFrom=f(n)),Object.freeze(r)}function s(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function f(t){var e=t.path,n=t.query;void 0===n&&(n={});var r=t.hash;return void 0===r&&(r=""),(e||"/")+u(n)+r}function p(t,e){return e===mt?t===e:!!e&&(t.path&&e.path?t.path.replace(gt,"")===e.path.replace(gt,"")&&t.hash===e.hash&&h(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&h(t.query,e.query)&&h(t.params,e.params)))}function h(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 l(t,e){return 0===t.path.indexOf(e.path.replace(/\/$/,""))&&(!e.hash||t.hash===e.hash)&&d(t.query,e.query)}function d(t,e){for(var n in e)if(!(n in t))return!1;return!0}function y(n,r,o){var a="string"==typeof n?{path:n}:n;if(a.name||a._normalized)return a;var u=e(a.path||""),c=r&&r.path||"/",s=u.path?t(u.path,c,o):r&&r.path||"/",f=i(u.query,a.query),p=a.hash||u.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:s,query:f,hash:p}}function v(t){if(t)for(var e,n=0;n-1&&(r.params[c]=e.params[c]);if(i)return r.path=B(i.path,r.params,'named route "'+o+'"'),a(i,r,n)}else if(r.path){r.params={};for(var p in s)if(M(p,r.params,r.path))return a(s[p],r,n)}return a(null,r)}function n(t,n){var i=t.redirect,u="function"==typeof i?i(c(t,n)):i;if("string"==typeof u&&(u={path:u}),!u||"object"!=typeof u)return o(!1,"invalid redirect option: "+JSON.stringify(u)),a(null,n);var s=u,p=s.name,h=s.path,l=n.query,d=n.hash,y=n.params;if(l=s.hasOwnProperty("query")?s.query:l,d=s.hasOwnProperty("hash")?s.hash:d,y=s.hasOwnProperty("params")?s.params:y,p){var v=f[p];return r(v,'redirect failed: named route "'+p+'" not found.'),e({_normalized:!0,name:p,query:l,hash:d,params:y},void 0,n)}if(h){var m=z(h,t),g=B(m,y,'redirect route with path "'+m+'"');return e({_normalized:!0,path:g,query:l,hash:d},void 0,n)}return o(!1,"invalid redirect option: "+JSON.stringify(u)),a(null,n)}function i(t,n,r){var o=B(r,n.params,'aliased route with path "'+r+'"'),i=e({_normalized:!0,path:o});if(i){var u=i.matched,c=u[u.length-1];return n.params=i.params,a(c,n)}return a(null,n)}function a(t,e,r){return t&&t.redirect?n(t,r||e):t&&t.matchAs?i(t,e,t.matchAs):c(t,e,r)}var u=C(t),s=u.pathMap,f=u.nameMap;return e}function V(t){var e,n,r=_t[t];return r?(e=r.keys,n=r.regexp):(e=[],n=Ot(t,e),_t[t]={keys:e,regexp:n}),{keys:e,regexp:n}}function M(t,e,n){var r=V(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 I(t){if(!t)if(qt){var e=document.querySelector("base");t=e?e.getAttribute("href"):"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function D(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}var lt,dt={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,o=e.parent,i=e.data;i.routerView=!0;for(var a=o.$route,u=o._routerViewCache||(o._routerViewCache={}),c=0,s=!1;o;)o.$vnode&&o.$vnode.data.routerView&&c++,o._inactive&&(s=!0),o=o.$parent;i.routerViewDepth=c;var f=a.matched[c];if(!f)return t();var p=n.name,h=s?u[p]:u[p]=f.components[p];if(!s){var l=i.hook||(i.hook={});l.init=function(t){f.instances[p]=t.child},l.prepatch=function(t,e){f.instances[p]=e.child},l.destroy=function(t){f.instances[p]===t.child&&(f.instances[p]=void 0)}}return t(h,i,r)}},yt=encodeURIComponent,vt=decodeURIComponent,mt=c(null,{path:"/"}),gt=/\/$/,wt=[String,Object],bt={name:"router-link",props:{to:{type:wt,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String},render:function(t){var e=this,n=this.$router,r=this.$route,o=y(this.to,r,this.append),i=n.match(o,r),a=i.redirectedFrom||i.fullPath,u=n.history.base,s=m(u,a,n.mode),f={},h=this.activeClass||n.options.linkActiveClass||"router-link-active",d=o.path?c(null,o):i;f[h]=this.exact?p(r,d):l(r,d);var g={click:function(t){if(!(t.metaKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||0!==t.button)){var r=t.target.getAttribute("target");/\b_blank\b/i.test(r)||(t.preventDefault(),e.replace?n.replace(o):n.push(o))}}},w={class:f};if("a"===this.tag)w.on=g,w.attrs={href:s};else{var b=v(this.$slots.default);if(b){b.isStatic=!1;var x=lt.util.extend,k=b.data=x({},b.data);k.on=g;var O=b.data.attrs=x({},b.data.attrs);O.href=s}else w.on=g}return t(this.tag,w,this.$slots.default)}},xt=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},kt=xt,Ot=q,Et=w,jt=b,Rt=O,At=T,$t=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");Ot.parse=Et,Ot.compile=jt,Ot.tokensToFunction=Rt,Ot.tokensToRegExp=At;var _t=Object.create(null),St=Object.create(null),Tt=Object.create(null),qt="undefined"!=typeof window,Ct=qt&&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)}(),Pt=function(t,e){this.router=t,this.base=I(e),this.current=mt,this.pending=null};Pt.prototype.listen=function(t){this.cb=t},Pt.prototype.transitionTo=function(t,e){var n=this,r=this.router.match(t,this.current);this.confirmTransition(r,function(){n.updateRoute(r),e&&e(r),n.ensureURL()})},Pt.prototype.confirmTransition=function(t,e){var n=this,r=this.current;if(p(t,r))return void this.ensureURL();var o=D(this.current.matched,t.matched),i=o.deactivated,a=o.activated,u=[].concat(N(i),this.router.beforeHooks,a.map(function(t){return t.beforeEnter}),G(a));this.pending=t;var c=function(e,o){n.pending===t&&e(t,r,function(t){t===!1?n.ensureURL(!0):"string"==typeof t||"object"==typeof t?n.push(t):o(t)})};F(u,c,function(){var r=[],o=X(a,r,function(){return n.current===t});F(o,c,function(){n.pending===t&&(n.pending=null,e(t),n.router.app.$nextTick(function(){r.forEach(function(t){return t()})}))})})},Pt.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 Ut=Object.create(null),Lt=function(){return String(Date.now())},Vt=Lt(),Mt=function(t){function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavior;window.addEventListener("popstate",function(t){Vt=t.state&&t.state.key;var e=r.current;r.transitionTo(at(r.base),function(t){o&&r.handleScroll(t,e,!0)})}),o&&window.addEventListener("scroll",function(){tt(Vt)})}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){var e=this,r=this.current;this.transitionTo(t,function(t){ut(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.replace=function(t){var e=this,r=this.current;this.transitionTo(t,function(t){ct(n(e.base+t.fullPath)),e.handleScroll(t,r,!1)})},e.prototype.ensureURL=function(t){if(at(this.base)!==this.current.fullPath){var e=n(this.base+this.current.fullPath);t?ut(e):ct(e)}},e.prototype.handleScroll=function(t,e,n){var o=this.router;if(o.app){var i=o.options.scrollBehavior;i&&(r("function"==typeof i,"scrollBehavior must be a function"),o.app.$nextTick(function(){var r=et(Vt),o=i(t,e,n?r:null);if(o){var a="object"==typeof o;if(a&&"string"==typeof o.selector){var u=document.querySelector(o.selector);u?r=nt(u):rt(o)&&(r=ot(o))}else a&&rt(o)&&(r=ot(o));r&&window.scrollTo(r.x,r.y)}}))}},e}(Pt),Bt=function(t){function e(e,n,r){t.call(this,e,n),r&&this.checkFallback()||st()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.checkFallback=function(){var t=at(this.base);if(!/^\/#/.test(t))return window.location.replace(n(this.base+"/#"+t)),!0},e.prototype.onHashChange=function(){st()&&this.transitionTo(ft(),function(t){ht(t.fullPath)})},e.prototype.push=function(t){this.transitionTo(t,function(t){pt(t.fullPath)})},e.prototype.replace=function(t){this.transitionTo(t,function(t){ht(t.fullPath)})},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;ft()!==e&&(t?pt(e):ht(e))},e}(Pt),Ht=function(t){function e(e){t.call(this,e),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){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index+1).concat(t),e.index++})},e.prototype.replace=function(t){var e=this;this.transitionTo(t,function(t){e.stack=e.stack.slice(0,e.index).concat(t)})},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.ensureURL=function(){},e}(Pt),zt=function(t){void 0===t&&(t={}),this.app=null,this.options=t,this.beforeHooks=[],this.afterHooks=[],this.match=L(t.routes||[]);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Ct,this.fallback&&(e="hash"),qt||(e="abstract"),this.mode=e,e){case"history":this.history=new Mt(this,t.base);break;case"hash":this.history=new Bt(this,t.base,this.fallback);break;case"abstract":this.history=new Ht(this);break;default:r(!1,"invalid mode: "+e)}},Ft={currentRoute:{}};return Ft.currentRoute.get=function(){return this.history&&this.history.current},zt.prototype.init=function(t){var e=this;r(g.installed,"not installed. Make sure to call `Vue.use(VueRouter)` before creating root instance."),this.app=t;var n=this.history;n instanceof Mt?n.transitionTo(at(n.base)):n instanceof Bt&&n.transitionTo(ft(),function(){window.addEventListener("hashchange",function(){n.onHashChange()})}),n.listen(function(t){e.app._route=t})},zt.prototype.beforeEach=function(t){this.beforeHooks.push(t)},zt.prototype.afterEach=function(t){this.afterHooks.push(t)},zt.prototype.push=function(t){this.history.push(t)},zt.prototype.replace=function(t){this.history.replace(t)},zt.prototype.go=function(t){this.history.go(t)},zt.prototype.back=function(){this.go(-1)},zt.prototype.forward=function(){this.go(1)},zt.prototype.getMatchedComponents=function(){return this.currentRoute?[].concat.apply([],this.currentRoute.matched.map(function(t){return Object.keys(t.components).map(function(e){return t.components[e]})})):[]},Object.defineProperties(zt.prototype,Ft),zt.install=g,qt&&window.Vue&&window.Vue.use(zt),zt}); \ No newline at end of file From 889d4c06809904157a890e9ac7da38ab963d2953 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 18 Nov 2016 11:05:01 -0500 Subject: [PATCH 12/12] [release] 2.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63a090a8b..1eb0eced3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-router", - "version": "2.0.2", + "version": "2.0.3", "description": "Official router for Vue.js 2.0", "author": "Evan You", "license": "MIT",