Closed roonie007 closed 2 years ago
Duplicate of https://github.com/vuejs/vue-router/issues/974
Note you can pass a random query parameter to force a navigation:
router.push({ query: { _r: Date.now() }})
Note you can pass a random query parameter to force a navigation:
router.push({ query: { _r: Date.now() }})
Already tried that, but it's a hack and it will just pollute the url, I am looking for a cleaner solution.
Duplicate of vuejs/vue-router#974
I am not sure that's a duplication since it's on a different repo and it's not the same version, more than that it's opened since 2016, i think it's completely ignored by Vue core team.
An undocumented argument called force
can be used to force refresh the page, regardless of whether the URL or path is the same as the current location.
@posva Perhaps it's worth adding to the documentation?
It's not documented for a reason π . Don't rely on it as it could be removed in the future.
Let's hope not π
What do you think about doing this?
await router.push({ path: '/' })
router.go(0)
if delta equals 0, it has the same result as calling location.reload() https://developer.mozilla.org/en-US/docs/Web/API/History/go
Was annoyed by a slightly different use case: fetching data in mounted
which wasn't called if you navigate within the same route with different params (e.g. from /user/joe
to /user/jane
).
Official documentation suggests a pattern of having to watch
params in addition to mount
, which is a bit too repetitive for my taste, so I finally ended up with <RouterView :key="$route.url"/>
which does the job.
If you don't rely on params and different URLs, you can create a global variable, assign a random value in one of the navigation guards, and use that as a key for router view. This way URL doesn't get polluted, and the components are correctly mounted/unmounted on every navigation. You can also customize this behaviour by placing the key
on different RouterView levels (in case you have hierarchies or nesting) or by scoping the navigation guards.
many thanks @inca π I was pulling my hair out with the same problem and I didn't think about your solution. this totally solves my problem
BTW, you donβt need the repetition: using one watch with immediate true is enough (no key on router view) This is more performant than using a key
Interesting. So, what I'm about to say is probably very controversial in Vue community (and kind of off topic), so sorry in advance. IMO/YMMV implied everywhere.
But here goes:
I tend to stay away from watch
, and not because of performance problems (it's as performant as other Vue's reactive stuff like computed props and template expressions), but because it breaks the declarativeness of the view layer of the application. I.e. instead of thinking "here's my data, I expect it (and all its deps) to be rendered" you start thinking "when data changes, do something" which is, in my opinion, a slippery path to causality issues and ultimately a lot of π and debugging. (In fact I've just checked, I've built very big and very dynamic applications and managed to not use watch
not even once, and this is something I recommend to not do to the teammates as well.)
I don't really care that much about DOM reusing on router changes. Unless you're doing something really DOM-heavy, you (and, more importantly, your users) won't notice a performance impact of remounting anyway. In this case it also comes at the expense of DX (because as mentioned above, I don't really like thinking in watch
terms). The mere fact that Vue Router doesn't have an option to key the RouterView by the props it injects makes me really sad (and occasionally want to build a plugin or similar) β because keying them manually is also tedious and somewhat error prone if you have complex route hierarchy.
I guess the justification for my case is that I only have 3 level nesting, and re-mounting matters only on the last level. In my head even though it's a hack it's still applied only on a couple of layouts (as opposed to every route component) and therefore is much better localized than watch
(which is also a hack to be frank).
How to do this and keep query parameters?
The simplest solution is to add a :key attribute to
// Vuejs 2
<router-view :key="$route.fullPath"></router-view>
// Vuejs 3
<router-view :key="route.fullPath"></router-view>
<script>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
This is because Vue Router does not notice any change if the same component is being addressed. With the key, any change to the path will trigger a reload of the component with the new data.
The simplest solution is to add a :key attribute to :
// Vuejs 2
<router-view :key="$route.fullPath"></router-view>
// Vuejs 3
<router-view :key="route.fullPath"></router-view>
<script>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
This is because Vue Router does not notice any change if the same component is being addressed. With the key, any change to the path will trigger a reload of the component with the new data.
The solutions from @edmidev seems to work fine. I was trying to use the "force" parameter from the docs like this:
<RouterLink :to={ path: url, force:true }></RouterLink>
But is not working (at least for me or my setup). Also, I tested the watcher way and seems to work too.
Just for a bit of context.
In my case, I have different routes for pages that build up dynamically and share the same DefaultView (kinda similar to a page builder). So, when the page loads, I read my page builder config three and load all the content block components.
I'm using v4.3.3 of the router.
It kinda feel that the right way is to force the reload like when reloading a page but I will stick to this workaround for now.
Version
4.0.12
Reproduction link
codesandbox.io
Steps to reproduce
Simply add a router-link to a view that points to the current page. Then click on that link multiple times, the page or the router-view does not reload or refresh
What is expected?
Refresh or reload the router-view ( same as any HTML a tag )
What is actually happening?
Nothing