question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[2.0] scrollBehavior doesn't store a scrolling position on the first page

See original GitHub issue

Vue.js & vue-router version

2.0.2, 2.0.1

Steps to reproduce

http://jsfiddle.net/sergeymakinen/zfwhp07p/

  • Click some Go to… links
  • Click Go back links until you’re back
  • Watch the browser’s console

Expected

scrollBehavior callback should return all saved positions on all pages back to the start page.

Actually happens

Instead the callback returns all except the very first page saved positions. It looks like there should be some replaceState call with a generated key when history mode initializes to be able to catch the key later in popstate.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:11 (1 by maintainers)

github_iconTop GitHub Comments

9reactions
woshizjacommented, Oct 22, 2016

I read the vue-router.js source code, when you click browser history back button,the following things will happen:

**1.**popstate event triggered,then we here:

window.addEventListener('popstate', function (e) {
      _key = e.state && e.state.key
      var current = this$1.current
      this$1.transitionTo(getLocation(this$1.base), function (next) {
        if (expectScroll) {
          this$1.handleScroll(next, current, true)
        }
      })
})

Note that the original history entry (for http://example.com/example.html) has no state object associated with it.

So, _key will be null.

**2.**Then, the program will run into this handleScroll function:

HTML5History.prototype.handleScroll = function handleScroll (to, from, isPop) {
    ......
    // wait until re-render finishes before scrolling
    router.app.$nextTick(function () {
      ......
    })
  };
  return HTML5History;
}(History));

**3.**There is a $nextTick function, so program will run into it:

// content of $nextTick()
var position = getScrollPosition(_key)

// injection position only when isPop
var shouldScroll = behavior(to, from, isPop ? position : null)
if (!shouldScroll) {
    return
}
var isObject = typeof shouldScroll === 'object'
// deal hash string ......
 if (position) {
      window.scrollTo(position.x, position.y)
 }

Because the _key is null, so getScrollPosition(_key) will return null. My config:

const router = new VueRouter({
    routes,
    mode: 'history',
    scrollBehavior(to, from, savedPosition) {
        console.log(savedPosition)
        if (savedPosition) {
            return savedPosition
        } else {
            return { x: 0, y: 100 }
        }
    }
});

shouldScroll will be {x:0, y:0}, program will run window.scrollTo(position.x, position.y), then page will scroll to top temporarily.

Attention: temporarily!

Continue running the program, The page will scroll to its original location, scrollTop(0, 100) will be invalid! It doesn’t work like the doc said:

This will simply make the page scroll to top for all route navigations.

I am very confused!

4.vue-router will listen ‘scroll’ event:

if (expectScroll) {
    window.addEventListener('scroll', function () {
        saveScrollPosition(_key)
    })
}

_key is null, won’t save position. But, when you already back to last page,your scroll behavior also trigger this,and the _key will have a value, because:

var genKey = function () { return String(Date.now()); }
var _key = genKey()

Now, I’m not sure I know how to use vue-router scrollBehavior.

4reactions
ghostcommented, Jun 11, 2017

I’ve been struggling with the same problem.

When the router is initialized, the current route R1 does not have state registered in the history (window.history.state -> null). Let’s say that R1 contains a long list view and the user scrolls to the bottom, so that window.scrollY becomes 2500.

Now the user navigates to another route R2 by clicking one of the list items. The scroll position of R1 ({ x: 0, y: 2500 }) is saved to the positionStore (scroll.js#L7). When clicking the back button, popstate event callback receives info about R1. Since it does not have its history state registered (e.state = null), no expected scrolling takes place. That’s where it breaks.

My current workaround is to replace the history state of the current route when the router is initialized. I just added pushState(cleanPath(this.getCurrentLocation()), true) to the HTML5History constructor. The critical part is to have the generated key added to the first route’s state.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[2.0] scrollBehavior doesn't store a scrolling position on the first page
[2.0] scrollBehavior doesn't store a scrolling position on the first page.
Read more >
Vue.js scroll to top of new page route after setTimeout
I'd like to wait 100ms before it automatically scrolls to the top. The following code doesn't end up scrolling at all. Is there...
Read more >
Scroll Behavior | Vue Router
When using client-side routing, we may want to scroll to top when navigating to a new route, or preserve the scrolling position of...
Read more >
How To Implement Smooth Scrolling in React - DigitalOcean
Smooth scrolling is when instead of clicking on a button and being instantly taken to a different part of the same page, ...
Read more >
scroll-behavior - CSS: Cascading Style Sheets - MDN Web Docs
The scroll-behavior CSS property sets the behavior for a scrolling box when ... overflow-y: scroll; scroll-behavior: smooth; } .scroll-page ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found