diff --git a/dist/vue-router.js b/dist/vue-router.js index 6b7214d47..74dc8c71f 100644 --- a/dist/vue-router.js +++ b/dist/vue-router.js @@ -185,13 +185,15 @@ return true } - function assert (condition, message) { + /* */ + + function assert (condition , message ) { if (!condition) { throw new Error(("[vue-router] " + message)) } } - function warn (condition, message) { + function warn (condition , message ) { if (!condition) { typeof console !== 'undefined' && console.warn(("[vue-router] " + message)) } @@ -404,7 +406,7 @@ beforeCreate: function beforeCreate () { if (this.$options.router) { this._router = this.$options.router - this._router.app = this + this._router.init(this) Vue.util.defineReactive(this, '_route', this._router.history.current) } } @@ -1034,7 +1036,7 @@ hash: hash }, undefined, location) } else { - warn(("invalid redirect option: " + (JSON.stringify(redirect)))) + warn(false, ("invalid redirect option: " + (JSON.stringify(redirect)))) return createRouteContext(null, location) } } @@ -1104,7 +1106,7 @@ (regexpCompileCache[path] = Regexp.compile(path)) return filler(params || {}, { pretty: true }) } catch (e) { - assert(("missing param for " + routeMsg + ": " + (e.message))) + assert(false, ("missing param for " + routeMsg + ": " + (e.message))) return '' } } @@ -1201,7 +1203,7 @@ // deactivate guards extractLeaveGuards(deactivated), // global before hooks - nomralizeGuards(this.router.options.beforeEach), + this.router.beforeHooks, // activate guards activated.map(function (m) { return m.beforeEnter; }) ).filter(function (_) { return _; }) @@ -1224,7 +1226,7 @@ History.prototype.updateRoute = function updateRoute (route ) { this.current = route this.cb && this.cb(route) - nomralizeGuards(this.router.options.afterEach).forEach(function (hook) { + this.router.afterHooks.forEach(function (hook) { hook && hook(route) }) }; @@ -1271,16 +1273,6 @@ } } - function nomralizeGuards (guards ) { - if (!guards) { - return [] - } - if (typeof guards === 'function') { - return [guards] - } - return guards - } - function extractLeaveGuards (matched ) { return Array.prototype.concat.apply([], matched.map(function (m) { return Object.keys(m.components).map(function (key) { @@ -1298,6 +1290,45 @@ }).reverse()) } + /* */ + + function saveScrollPosition (key ) { + if (!key) return + window.sessionStorage.setItem(key, JSON.stringify({ + x: window.pageXOffset, + y: window.pageYOffset + })) + } + + function getScrollPosition (key ) { + if (!key) return + return JSON.parse(window.sessionStorage.getItem(key)) + } + + function getElementPosition (el ) { + var docRect = document.documentElement.getBoundingClientRect() + var elRect = el.getBoundingClientRect() + return { + x: elRect.left - docRect.left, + y: elRect.top - docRect.top + } + } + + function isValidPosition (obj ) { + return isNumber(obj.x) || isNumber(obj.y) + } + + function normalizePosotion (obj ) { + return { + x: isNumber(obj.x) ? obj.x : window.pageXOffset, + y: isNumber(obj.y) ? obj.y : window.pageYOffset + } + } + + function isNumber (v ) { + return typeof v === 'number' + } + var genKey = function () { return String(Date.now()); } var _key = genKey() @@ -1326,7 +1357,9 @@ }) if (expectScroll) { - window.addEventListener('scroll', saveScrollPosition) + window.addEventListener('scroll', function () { + saveScrollPosition(_key) + }) } } @@ -1372,30 +1405,25 @@ if (!behavior) { return } - assert(typeof behavior === 'function', "scrollBehavior must be a function") - var position = getScrollPosition() - var shouldScroll = behavior(to, from, isPop ? position : null) - if (!shouldScroll) { - return - } - // wait until re-render finishes before scrolling router.app.$nextTick(function () { + var position = getScrollPosition(_key) + var shouldScroll = behavior(to, from, isPop ? position : null) + if (!shouldScroll) { + return + } var isObject = typeof shouldScroll === 'object' - if (isObject && shouldScroll.x != null && shouldScroll.y != null) { - position = shouldScroll - } else if (isObject && shouldScroll.anchor) { - var el = document.querySelector(to.hash) + if (isObject && shouldScroll.selector) { + var el = document.querySelector(shouldScroll.selector) if (el) { - var docTop = document.documentElement.getBoundingClientRect().top - var elTop = el.getBoundingClientRect().top - position = { - x: window.scrollX, - y: elTop - docTop - } + position = getElementPosition(el) + } else if (isValidPosition(shouldScroll)) { + position = normalizePosotion(shouldScroll) } + } else if (isObject && isValidPosition(shouldScroll)) { + position = normalizePosotion(shouldScroll) } if (position) { @@ -1426,7 +1454,7 @@ _key = genKey() history.pushState({ key: _key }, '', url) } - saveScrollPosition() + saveScrollPosition(_key) } catch (e) { window.location[replace ? 'assign' : 'replace'](url) } @@ -1436,19 +1464,6 @@ pushState(url, true) } - function saveScrollPosition () { - if (!_key) return - window.sessionStorage.setItem(_key, JSON.stringify({ - x: window.pageXOffset, - y: window.pageYOffset - })) - } - - function getScrollPosition () { - if (!_key) return - return JSON.parse(window.sessionStorage.getItem(_key)) - } - var HashHistory = (function (History) { function HashHistory (router , base , fallback ) { var this$1 = this; @@ -1595,28 +1610,38 @@ }(History)); var VueRouter = function VueRouter (options) { - var this$1 = this; if ( options === void 0 ) options = {}; - assert( - install.installed, - "not installed. Make sure to call `Vue.use(VueRouter)` " + - "before mounting root instance." - ) - this.app = null this.options = options + this.beforeHooks = [] + this.afterHooks = [] this.match = createMatcher(options.routes || []) var mode = options.mode || 'hash' - var fallback = mode === 'history' && !supportsHistory - if (fallback) { + this.fallback = mode === 'history' && !supportsHistory + if (this.fallback) { mode = 'hash' } if (!inBrowser) { mode = 'abstract' } + this.mode = mode + }; + + VueRouter.prototype.init = function init (app /* Vue component instance */) { + var this$1 = this; + + assert( + install.installed, + "not installed. Make sure to call `Vue.use(VueRouter)` " + + "before creating root instance." + ) + 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) @@ -1631,26 +1656,33 @@ assert(false, ("invalid mode: " + mode)) } - this.mode = mode - + this.app = app this.history.listen(function (route) { this$1.app._route = route }) }; + VueRouter.prototype.beforeEach = function beforeEach (fn ) { + this.beforeHooks.push(fn) + }; + + VueRouter.prototype.afterEach = function afterEach (fn ) { + this.afterHooks.push(fn) + }; + VueRouter.prototype.push = function push (location ) { this.history.push(location) }; VueRouter.prototype.replace = function replace (location ) { this.history.replace(location) - }; + }; - VueRouter.prototype.go = function go (n ) { - this.history.go(n) - }; + VueRouter.prototype.go = function go (n ) { + this.history.go(n) + }; - VueRouter.prototype.back = function back () { + VueRouter.prototype.back = function back () { this.go(-1) }; diff --git a/dist/vue-router.min.js b/dist/vue-router.min.js index 4a210c11b..61017bdf0 100644 --- a/dist/vue-router.min.js +++ b/dist/vue-router.min.js @@ -1 +1 @@ -!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(void 0===e&&(e="/"),"/"===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){return!!e&&(t.path&&e.path?t.path===e.path&&t.hash===e.hash&&o(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&o(t.query,e.query)&&o(t.params,e.params)))}function o(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 i(t,e){return 0===t.path.indexOf(e.path)&&(!e.hash||t.hash===e.hash)&&a(t.query,e.query)}function a(t,e){for(var n in e)if(!(n in t))return!1;return!0}function c(t,e){if(!t)throw new Error("[vue-router] "+e)}function u(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function s(t,e){if(void 0===e&&(e={}),t){var n;try{n=p(t)}catch(t){u(!1,t.message),n={}}for(var r in e)n[r]=e[r];return n}return e}function p(t){var e=Object.create(null);return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=F(n.shift()),o=n.length>0?F(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 h(t){var e=t?Object.keys(t).sort().map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return M(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(M(e)):r.push(M(e)+"="+M(t)))}),r.join("&")}return M(e)+"="+M(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function f(n,r,o){var i="string"==typeof n?{path:n}:n;if(i.name||i._normalized)return i;var a=e(i.path||""),c=a.path?t(a.path,r&&r.path,o):r&&r.path||"/",u=s(a.query,i.query),p=i.hash||a.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:c,query:u,hash:p}}function l(t){if(t)for(var e,n=0;n=t.length?n():e(t[o],function(){r(o+1)})};r(0)}function S(t){if(!t)if(K){var e=document.querySelector("base");t=e?e.getAttribute("href"):"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function _(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}var z={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,c=o._routerViewCache||(o._routerViewCache={}),u=0,s=!1;o;)o.$vnode&&o.$vnode.data.routerView&&u++,o._inactive&&(s=!0),o=o.$parent;i.routerViewDepth=u;var p=a.matched[u];if(!p)return t();var h=s?c[n.name]:c[n.name]=p.components[n.name],f=t(h,i,r);return s||(p.instances[n.name]=f),f}},M=encodeURIComponent,F=decodeURIComponent,J={name:"router-link",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String},render:function(t){var e=this,o=this.$router,a=this.$route,c=f(this.to,a,this.append),u=o.match(c),s=u.redirectedFrom||u.fullPath,p=o.history.base,h=p?n(p+s):s,d={},y=this.activeClass||o.options.linkActiveClass||"router-link-active";d[y]=this.exact?r(a,u):i(a,u);var v={class:d,on:{click:function(t){t.preventDefault(),e.replace?o.replace(c):o.push(c)}}};if("a"===this.tag)v.attrs={href:h};else{var m=l(this.$slots.default);if(m){var g=m.data||(m.data={}),w=g.attrs||(g.attrs={});w.href=h}}return t(this.tag,v,this.$slots.default)}},N=v(function(t){t.exports=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)}}),D=y(N),H=Object.freeze({default:D}),X=v(function(t){function e(t){for(var e,n=[],r=0,o=0,i="";null!=(e=m.exec(t));){var a=e[0],u=e[1],s=e.index;if(i+=t.slice(o,s),o=s+a.length,u)i+=u[1];else{var p=t[o],h=e[2],f=e[3],l=e[4],d=e[5],y=e[6],v=e[7];i&&(n.push(i),i="");var g=null!=h&&null!=p&&p!==h,w="+"===y||"*"===y,b="?"===y||"*"===y,x=e[2]||"/",k=l||d||(v?".*":"[^"+x+"]+?");n.push({name:f||r++,prefix:h||"",delimiter:x,optional:b,repeat:w,partial:g,asterisk:!!v,pattern:c(k)})}}return o=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,function(){e.index=n,e.updateRoute(r)})}},e.prototype.setInitialRoute=function(t){this.current=t,this.stack=[this.current],this.index=0},e}(Z),it=function(t){var e=this;void 0===t&&(t={}),c(d.installed,"not installed. Make sure to call `Vue.use(VueRouter)` before mounting root instance."),this.app=null,this.options=t,this.match=b(t.routes||[]);var n=t.mode||"hash",r="history"===n&&!Q;switch(r&&(n="hash"),K||(n="abstract"),n){case"history":this.history=new nt(this,t.base);break;case"hash":this.history=new rt(this,t.base,r);break;case"abstract":this.history=new ot(this);break;default:c(!1,"invalid mode: "+n)}this.mode=n,this.history.listen(function(t){e.app._route=t})};return it.prototype.push=function(t){this.history.push(t)},it.prototype.replace=function(t){this.history.replace(t)},it.prototype.go=function(t){this.history.go(t)},it.prototype.back=function(){this.go(-1)},it.prototype.forward=function(){this.go(1)},it.prototype.setInitialLocation=function(t){this.history instanceof ot&&this.history.setInitialRoute(this.match(t))},it.install=d,K&&window.Vue&&window.Vue.use(it),it}); \ 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(void 0===e&&(e="/"),"/"===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){return!!e&&(t.path&&e.path?t.path===e.path&&t.hash===e.hash&&o(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&o(t.query,e.query)&&o(t.params,e.params)))}function o(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 i(t,e){return 0===t.path.indexOf(e.path)&&(!e.hash||t.hash===e.hash)&&a(t.query,e.query)}function a(t,e){for(var n in e)if(!(n in t))return!1;return!0}function c(t,e){if(!t)throw new Error("[vue-router] "+e)}function u(t,e){t||"undefined"!=typeof console&&console.warn("[vue-router] "+e)}function s(t,e){if(void 0===e&&(e={}),t){var n;try{n=p(t)}catch(t){u(!1,t.message),n={}}for(var r in e)n[r]=e[r];return n}return e}function p(t){var e=Object.create(null);return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=N(n.shift()),o=n.length>0?N(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 h(t){var e=t?Object.keys(t).sort().map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return J(e);if(Array.isArray(n)){var r=[];return n.slice().forEach(function(t){void 0!==t&&(null===t?r.push(J(e)):r.push(J(e)+"="+J(t)))}),r.join("&")}return J(e)+"="+J(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}function f(n,r,o){var i="string"==typeof n?{path:n}:n;if(i.name||i._normalized)return i;var a=e(i.path||""),c=a.path?t(a.path,r&&r.path,o):r&&r.path||"/",u=s(a.query,i.query),p=i.hash||a.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:c,query:u,hash:p}}function l(t){if(t)for(var e,n=0;n=t.length?n():e(t[o],function(){r(o+1)})};r(0)}function S(t){if(!t)if(tt){var e=document.querySelector("base");t=e?e.getAttribute("href"):"/"}else t="/";return"/"!==t.charAt(0)&&(t="/"+t),t.replace(/\/$/,"")}function _(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n=0?e:0)+"#"+t)}var F={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,c=o._routerViewCache||(o._routerViewCache={}),u=0,s=!1;o;)o.$vnode&&o.$vnode.data.routerView&&u++,o._inactive&&(s=!0),o=o.$parent;i.routerViewDepth=u;var p=a.matched[u];if(!p)return t();var h=s?c[n.name]:c[n.name]=p.components[n.name],f=t(h,i,r);return s||(p.instances[n.name]=f),f}},J=encodeURIComponent,N=decodeURIComponent,D={name:"router-link",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String},render:function(t){var e=this,o=this.$router,a=this.$route,c=f(this.to,a,this.append),u=o.match(c),s=u.redirectedFrom||u.fullPath,p=o.history.base,h=p?n(p+s):s,d={},y=this.activeClass||o.options.linkActiveClass||"router-link-active";d[y]=this.exact?r(a,u):i(a,u);var v={class:d,on:{click:function(t){t.preventDefault(),e.replace?o.replace(c):o.push(c)}}};if("a"===this.tag)v.attrs={href:h};else{var m=l(this.$slots.default);if(m){var g=m.data||(m.data={}),w=g.attrs||(g.attrs={});w.href=h}}return t(this.tag,v,this.$slots.default)}},X=v(function(t){t.exports=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)}}),Y=y(X),W=Object.freeze({default:Y}),G=v(function(t){function e(t){for(var e,n=[],r=0,o=0,i="";null!=(e=m.exec(t));){var a=e[0],u=e[1],s=e.index;if(i+=t.slice(o,s),o=s+a.length,u)i+=u[1];else{var p=t[o],h=e[2],f=e[3],l=e[4],d=e[5],y=e[6],v=e[7];i&&(n.push(i),i="");var g=null!=h&&null!=p&&p!==h,w="+"===y||"*"===y,b="?"===y||"*"===y,x=e[2]||"/",k=l||d||(v?".*":"[^"+x+"]+?");n.push({name:f||r++,prefix:h||"",delimiter:x,optional:b,repeat:w,partial:g,asterisk:!!v,pattern:c(k)})}}return o=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,function(){e.index=n,e.updateRoute(r)})}},e.prototype.setInitialRoute=function(t){this.current=t,this.stack=[this.current],this.index=0},e}(nt),ut=function(t){void 0===t&&(t={}),this.app=null,this.options=t,this.beforeHooks=[],this.afterHooks=[],this.match=b(t.routes||[]);var e=t.mode||"hash";this.fallback="history"===e&&!et,this.fallback&&(e="hash"),tt||(e="abstract"),this.mode=e};return ut.prototype.init=function(t){var e=this;c(d.installed,"not installed. Make sure to call `Vue.use(VueRouter)` before creating root instance.");var n=this,r=n.mode,o=n.options,i=n.fallback;switch(r){case"history":this.history=new it(this,o.base);break;case"hash":this.history=new at(this,o.base,i);break;case"abstract":this.history=new ct(this);break;default:c(!1,"invalid mode: "+r)}this.app=t,this.history.listen(function(t){e.app._route=t})},ut.prototype.beforeEach=function(t){this.beforeHooks.push(t)},ut.prototype.afterEach=function(t){this.afterHooks.push(t)},ut.prototype.push=function(t){this.history.push(t)},ut.prototype.replace=function(t){this.history.replace(t)},ut.prototype.go=function(t){this.history.go(t)},ut.prototype.back=function(){this.go(-1)},ut.prototype.forward=function(){this.go(1)},ut.prototype.setInitialLocation=function(t){this.history instanceof ct&&this.history.setInitialRoute(this.match(t))},ut.install=d,tt&&window.Vue&&window.Vue.use(ut),ut}); \ No newline at end of file