router.scrollBehavior.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <% if (router.scrollBehavior) { %>
  2. <%= isTest ? '/* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %>
  3. export default <%= serializeFunction(router.scrollBehavior) %>
  4. <%= isTest ? '/* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */' : '' %>
  5. <% } else { %>import { getMatchedComponents, setScrollRestoration } from './utils'
  6. if (process.client) {
  7. if ('scrollRestoration' in window.history) {
  8. setScrollRestoration('manual')
  9. // reset scrollRestoration to auto when leaving page, allowing page reload
  10. // and back-navigation from other pages to use the browser to restore the
  11. // scrolling position.
  12. window.addEventListener('beforeunload', () => {
  13. setScrollRestoration('auto')
  14. })
  15. // Setting scrollRestoration to manual again when returning to this page.
  16. window.addEventListener('load', () => {
  17. setScrollRestoration('manual')
  18. })
  19. }
  20. }
  21. function shouldScrollToTop(route) {
  22. const Pages = getMatchedComponents(route)
  23. if (Pages.length === 1) {
  24. const { options = {} } = Pages[0]
  25. return options.scrollToTop !== false
  26. }
  27. return Pages.some(({ options }) => options && options.scrollToTop)
  28. }
  29. export default function (to, from, savedPosition) {
  30. // If the returned position is falsy or an empty object, will retain current scroll position
  31. let position = false
  32. const isRouteChanged = to !== from
  33. // savedPosition is only available for popstate navigations (back button)
  34. if (savedPosition) {
  35. position = savedPosition
  36. } else if (isRouteChanged && shouldScrollToTop(to)) {
  37. position = { x: 0, y: 0 }
  38. }
  39. const nuxt = window.<%= globals.nuxt %>
  40. if (
  41. // Initial load (vuejs/vue-router#3199)
  42. !isRouteChanged ||
  43. // Route hash changes
  44. (to.path === from.path && to.hash !== from.hash)
  45. ) {
  46. nuxt.$nextTick(() => nuxt.$emit('triggerScroll'))
  47. }
  48. return new Promise((resolve) => {
  49. // wait for the out transition to complete (if necessary)
  50. nuxt.$once('triggerScroll', () => {
  51. // coords will be used if no selector is provided,
  52. // or if the selector didn't match any element.
  53. if (to.hash) {
  54. let hash = to.hash
  55. // CSS.escape() is not supported with IE and Edge.
  56. if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') {
  57. hash = '#' + window.CSS.escape(hash.substr(1))
  58. }
  59. try {
  60. if (document.querySelector(hash)) {
  61. // scroll to anchor by returning the selector
  62. position = { selector: hash }
  63. }
  64. } catch (e) {
  65. <%= isTest ? '// eslint-disable-next-line no-console' : '' %>
  66. console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).')
  67. }
  68. }
  69. resolve(position)
  70. })
  71. })
  72. }
  73. <% } %>