Vue-router: hashchange event not working in 2.8

Created on 13 Oct 2017  路  9Comments  路  Source: vuejs/vue-router

Version

2.8.0 & 3.0.0

Reproduction link

http://jsfiddle.net/9r6xhqbp/41/

Steps to reproduce

Switch between /home and /foo

What is expected?

hashchange triggers and you'll see 1s printed in the console.

What is actually happening?

Nothing is printed.


hashchange works fine in 2.7.0: http://jsfiddle.net/9r6xhqbp/40/

regression

Most helpful comment

In 2.8 & 3.0 hash mode will use pushState when it's available, which doesn't seem to trigger hashchange event anymore. This is unfortunately an unintended breaking behavior, although technically is not part of the API contract.

I'd recommend using a more implementation-agnostic way to detect route change, e.g. router.afterEach.

All 9 comments

In 2.8 & 3.0 hash mode will use pushState when it's available, which doesn't seem to trigger hashchange event anymore. This is unfortunately an unintended breaking behavior, although technically is not part of the API contract.

I'd recommend using a more implementation-agnostic way to detect route change, e.g. router.afterEach.

it can also be work like this instead of window.addEventListener('hashchange')
watch: {
'$route': function(){}
}

@yyx990803 Sorry I don't get why the default behavior overrides a well known configuration. If I use mode: 'hash' I expect an hash change, not a push state.

What about introducing a dedicated mode like mode: 'pushstate'? And maybe make it as a default one.

//EDIT: checking it again it seems there is already the history mode. See https://router.vuejs.org/en/api/options.html#mode

Does that mean you fixed it?

@julianxhokaxhiu hash mode only guarantees the URLs are expressed using the hash, but the hash may be changed by either pushState or direct hash mutation. The former does not emit the hashchange event.

The API has never made any guarantee on whether a hashchange event will be dispatched in hash mode. As suggested, you should use the router's own API to detect route change.

My target was not related to the Vue ecosystem, but other libraries that may interact with native DOM events.

I get that the library was not giving guarantee, but in my honest opinion I think that when you keep such a feature for long time, you definitely do not want to change it under the hood.
Instead you enable everything with a flag detecting if the user wants that feature too, because instead it is a feature ( aside the fact it is auto-detected anyway as a browser feature ), not a bugfix.

@julianxhokaxhiu for your use case, a very simple workaround: dispatch a hashchange event yourself in router.afterEach.

Sure, the workaround may work and it's fine. What happens if you have already that event dispatched? This means that you have to check if the push-state is supported first right? So again, this means overhead on top of a well known behavior.

Unless Vue Router gives a guarantee that the afterEach is called only when a push-state happens.

function pushHash (path) {
  if (supportsPushState) {
    pushState(getUrl(path));
  } else {
    window.location.hash = path;
  }
}

all because above

It also doesn't work in version 2.1.4

Was this page helpful?
0 / 5 - 0 ratings