|
185 | 185 | return true |
186 | 186 | } |
187 | 187 |
|
188 | | - function assert (condition, message) { |
| 188 | + /* */ |
| 189 | + |
| 190 | + function assert (condition , message ) { |
189 | 191 | if (!condition) { |
190 | 192 | throw new Error(("[vue-router] " + message)) |
191 | 193 | } |
192 | 194 | } |
193 | 195 |
|
194 | | - function warn (condition, message) { |
| 196 | + function warn (condition , message ) { |
195 | 197 | if (!condition) { |
196 | 198 | typeof console !== 'undefined' && console.warn(("[vue-router] " + message)) |
197 | 199 | } |
|
404 | 406 | beforeCreate: function beforeCreate () { |
405 | 407 | if (this.$options.router) { |
406 | 408 | this._router = this.$options.router |
407 | | - this._router.app = this |
| 409 | + this._router.init(this) |
408 | 410 | Vue.util.defineReactive(this, '_route', this._router.history.current) |
409 | 411 | } |
410 | 412 | } |
|
1034 | 1036 | hash: hash |
1035 | 1037 | }, undefined, location) |
1036 | 1038 | } else { |
1037 | | - warn(("invalid redirect option: " + (JSON.stringify(redirect)))) |
| 1039 | + warn(false, ("invalid redirect option: " + (JSON.stringify(redirect)))) |
1038 | 1040 | return createRouteContext(null, location) |
1039 | 1041 | } |
1040 | 1042 | } |
|
1104 | 1106 | (regexpCompileCache[path] = Regexp.compile(path)) |
1105 | 1107 | return filler(params || {}, { pretty: true }) |
1106 | 1108 | } catch (e) { |
1107 | | - assert(("missing param for " + routeMsg + ": " + (e.message))) |
| 1109 | + assert(false, ("missing param for " + routeMsg + ": " + (e.message))) |
1108 | 1110 | return '' |
1109 | 1111 | } |
1110 | 1112 | } |
|
1201 | 1203 | // deactivate guards |
1202 | 1204 | extractLeaveGuards(deactivated), |
1203 | 1205 | // global before hooks |
1204 | | - nomralizeGuards(this.router.options.beforeEach), |
| 1206 | + this.router.beforeHooks, |
1205 | 1207 | // activate guards |
1206 | 1208 | activated.map(function (m) { return m.beforeEnter; }) |
1207 | 1209 | ).filter(function (_) { return _; }) |
|
1224 | 1226 | History.prototype.updateRoute = function updateRoute (route ) { |
1225 | 1227 | this.current = route |
1226 | 1228 | this.cb && this.cb(route) |
1227 | | - nomralizeGuards(this.router.options.afterEach).forEach(function (hook) { |
| 1229 | + this.router.afterHooks.forEach(function (hook) { |
1228 | 1230 | hook && hook(route) |
1229 | 1231 | }) |
1230 | 1232 | }; |
|
1271 | 1273 | } |
1272 | 1274 | } |
1273 | 1275 |
|
1274 | | - function nomralizeGuards (guards ) { |
1275 | | - if (!guards) { |
1276 | | - return [] |
1277 | | - } |
1278 | | - if (typeof guards === 'function') { |
1279 | | - return [guards] |
1280 | | - } |
1281 | | - return guards |
1282 | | - } |
1283 | | - |
1284 | 1276 | function extractLeaveGuards (matched ) { |
1285 | 1277 | return Array.prototype.concat.apply([], matched.map(function (m) { |
1286 | 1278 | return Object.keys(m.components).map(function (key) { |
|
1298 | 1290 | }).reverse()) |
1299 | 1291 | } |
1300 | 1292 |
|
| 1293 | + /* */ |
| 1294 | + |
| 1295 | + function saveScrollPosition (key ) { |
| 1296 | + if (!key) return |
| 1297 | + window.sessionStorage.setItem(key, JSON.stringify({ |
| 1298 | + x: window.pageXOffset, |
| 1299 | + y: window.pageYOffset |
| 1300 | + })) |
| 1301 | + } |
| 1302 | + |
| 1303 | + function getScrollPosition (key ) { |
| 1304 | + if (!key) return |
| 1305 | + return JSON.parse(window.sessionStorage.getItem(key)) |
| 1306 | + } |
| 1307 | + |
| 1308 | + function getElementPosition (el ) { |
| 1309 | + var docRect = document.documentElement.getBoundingClientRect() |
| 1310 | + var elRect = el.getBoundingClientRect() |
| 1311 | + return { |
| 1312 | + x: elRect.left - docRect.left, |
| 1313 | + y: elRect.top - docRect.top |
| 1314 | + } |
| 1315 | + } |
| 1316 | + |
| 1317 | + function isValidPosition (obj ) { |
| 1318 | + return isNumber(obj.x) || isNumber(obj.y) |
| 1319 | + } |
| 1320 | + |
| 1321 | + function normalizePosotion (obj ) { |
| 1322 | + return { |
| 1323 | + x: isNumber(obj.x) ? obj.x : window.pageXOffset, |
| 1324 | + y: isNumber(obj.y) ? obj.y : window.pageYOffset |
| 1325 | + } |
| 1326 | + } |
| 1327 | + |
| 1328 | + function isNumber (v ) { |
| 1329 | + return typeof v === 'number' |
| 1330 | + } |
| 1331 | + |
1301 | 1332 | var genKey = function () { return String(Date.now()); } |
1302 | 1333 | var _key = genKey() |
1303 | 1334 |
|
|
1326 | 1357 | }) |
1327 | 1358 |
|
1328 | 1359 | if (expectScroll) { |
1329 | | - window.addEventListener('scroll', saveScrollPosition) |
| 1360 | + window.addEventListener('scroll', function () { |
| 1361 | + saveScrollPosition(_key) |
| 1362 | + }) |
1330 | 1363 | } |
1331 | 1364 | } |
1332 | 1365 |
|
|
1372 | 1405 | if (!behavior) { |
1373 | 1406 | return |
1374 | 1407 | } |
1375 | | - |
1376 | 1408 | assert(typeof behavior === 'function', "scrollBehavior must be a function") |
1377 | 1409 |
|
1378 | | - var position = getScrollPosition() |
1379 | | - var shouldScroll = behavior(to, from, isPop ? position : null) |
1380 | | - if (!shouldScroll) { |
1381 | | - return |
1382 | | - } |
1383 | | - |
1384 | 1410 | // wait until re-render finishes before scrolling |
1385 | 1411 | router.app.$nextTick(function () { |
| 1412 | + var position = getScrollPosition(_key) |
| 1413 | + var shouldScroll = behavior(to, from, isPop ? position : null) |
| 1414 | + if (!shouldScroll) { |
| 1415 | + return |
| 1416 | + } |
1386 | 1417 | var isObject = typeof shouldScroll === 'object' |
1387 | | - if (isObject && shouldScroll.x != null && shouldScroll.y != null) { |
1388 | | - position = shouldScroll |
1389 | | - } else if (isObject && shouldScroll.anchor) { |
1390 | | - var el = document.querySelector(to.hash) |
| 1418 | + if (isObject && shouldScroll.selector) { |
| 1419 | + var el = document.querySelector(shouldScroll.selector) |
1391 | 1420 | if (el) { |
1392 | | - var docTop = document.documentElement.getBoundingClientRect().top |
1393 | | - var elTop = el.getBoundingClientRect().top |
1394 | | - position = { |
1395 | | - x: window.scrollX, |
1396 | | - y: elTop - docTop |
1397 | | - } |
| 1421 | + position = getElementPosition(el) |
| 1422 | + } else if (isValidPosition(shouldScroll)) { |
| 1423 | + position = normalizePosotion(shouldScroll) |
1398 | 1424 | } |
| 1425 | + } else if (isObject && isValidPosition(shouldScroll)) { |
| 1426 | + position = normalizePosotion(shouldScroll) |
1399 | 1427 | } |
1400 | 1428 |
|
1401 | 1429 | if (position) { |
|
1426 | 1454 | _key = genKey() |
1427 | 1455 | history.pushState({ key: _key }, '', url) |
1428 | 1456 | } |
1429 | | - saveScrollPosition() |
| 1457 | + saveScrollPosition(_key) |
1430 | 1458 | } catch (e) { |
1431 | 1459 | window.location[replace ? 'assign' : 'replace'](url) |
1432 | 1460 | } |
|
1436 | 1464 | pushState(url, true) |
1437 | 1465 | } |
1438 | 1466 |
|
1439 | | - function saveScrollPosition () { |
1440 | | - if (!_key) return |
1441 | | - window.sessionStorage.setItem(_key, JSON.stringify({ |
1442 | | - x: window.pageXOffset, |
1443 | | - y: window.pageYOffset |
1444 | | - })) |
1445 | | - } |
1446 | | - |
1447 | | - function getScrollPosition () { |
1448 | | - if (!_key) return |
1449 | | - return JSON.parse(window.sessionStorage.getItem(_key)) |
1450 | | - } |
1451 | | - |
1452 | 1467 | var HashHistory = (function (History) { |
1453 | 1468 | function HashHistory (router , base , fallback ) { |
1454 | 1469 | var this$1 = this; |
|
1595 | 1610 | }(History)); |
1596 | 1611 |
|
1597 | 1612 | var VueRouter = function VueRouter (options) { |
1598 | | - var this$1 = this; |
1599 | 1613 | if ( options === void 0 ) options = {}; |
1600 | 1614 |
|
1601 | | - assert( |
1602 | | - install.installed, |
1603 | | - "not installed. Make sure to call `Vue.use(VueRouter)` " + |
1604 | | - "before mounting root instance." |
1605 | | - ) |
1606 | | - |
1607 | 1615 | this.app = null |
1608 | 1616 | this.options = options |
| 1617 | + this.beforeHooks = [] |
| 1618 | + this.afterHooks = [] |
1609 | 1619 | this.match = createMatcher(options.routes || []) |
1610 | 1620 |
|
1611 | 1621 | var mode = options.mode || 'hash' |
1612 | | - var fallback = mode === 'history' && !supportsHistory |
1613 | | - if (fallback) { |
| 1622 | + this.fallback = mode === 'history' && !supportsHistory |
| 1623 | + if (this.fallback) { |
1614 | 1624 | mode = 'hash' |
1615 | 1625 | } |
1616 | 1626 | if (!inBrowser) { |
1617 | 1627 | mode = 'abstract' |
1618 | 1628 | } |
| 1629 | + this.mode = mode |
| 1630 | + }; |
| 1631 | + |
| 1632 | + VueRouter.prototype.init = function init (app /* Vue component instance */) { |
| 1633 | + var this$1 = this; |
| 1634 | + |
| 1635 | + assert( |
| 1636 | + install.installed, |
| 1637 | + "not installed. Make sure to call `Vue.use(VueRouter)` " + |
| 1638 | + "before creating root instance." |
| 1639 | + ) |
1619 | 1640 |
|
| 1641 | + var ref = this; |
| 1642 | + var mode = ref.mode; |
| 1643 | + var options = ref.options; |
| 1644 | + var fallback = ref.fallback; |
1620 | 1645 | switch (mode) { |
1621 | 1646 | case 'history': |
1622 | 1647 | this.history = new HTML5History(this, options.base) |
|
1631 | 1656 | assert(false, ("invalid mode: " + mode)) |
1632 | 1657 | } |
1633 | 1658 |
|
1634 | | - this.mode = mode |
1635 | | - |
| 1659 | + this.app = app |
1636 | 1660 | this.history.listen(function (route) { |
1637 | 1661 | this$1.app._route = route |
1638 | 1662 | }) |
1639 | 1663 | }; |
1640 | 1664 |
|
| 1665 | + VueRouter.prototype.beforeEach = function beforeEach (fn ) { |
| 1666 | + this.beforeHooks.push(fn) |
| 1667 | + }; |
| 1668 | + |
| 1669 | + VueRouter.prototype.afterEach = function afterEach (fn ) { |
| 1670 | + this.afterHooks.push(fn) |
| 1671 | + }; |
| 1672 | + |
1641 | 1673 | VueRouter.prototype.push = function push (location ) { |
1642 | 1674 | this.history.push(location) |
1643 | 1675 | }; |
1644 | 1676 |
|
1645 | 1677 | VueRouter.prototype.replace = function replace (location ) { |
1646 | 1678 | this.history.replace(location) |
1647 | | - }; |
| 1679 | + }; |
1648 | 1680 |
|
1649 | | - VueRouter.prototype.go = function go (n ) { |
1650 | | - this.history.go(n) |
1651 | | - }; |
| 1681 | + VueRouter.prototype.go = function go (n ) { |
| 1682 | + this.history.go(n) |
| 1683 | + }; |
1652 | 1684 |
|
1653 | | - VueRouter.prototype.back = function back () { |
| 1685 | + VueRouter.prototype.back = function back () { |
1654 | 1686 | this.go(-1) |
1655 | 1687 | }; |
1656 | 1688 |
|
|
0 commit comments