简体   繁体   中英

Do we have router.reload in vue-router?

I see in this pull request :

  • Add a router.reload()

    Reload with current path and call data hook again

But when I try issuing the following command from a Vue component:

this.$router.reload()

I get this error:

Uncaught TypeError: this.$router.reload is not a function

I searched in the docs , but could not found anything relevant. Does vue/vue-router provider some functionality like this?

The software versions I'm interested in are:

"vue": "^2.1.0",
"vue-router": "^2.0.3",

PS. I know location.reload() is one of the alternatives, but I'm looking for a native Vue option.

this.$router.go() does exactly this; if no arguments are specified, the router navigates to current location, refreshing the page.

note: current implementation of router and its history components don't mark the param as optional, but IMVHO it's either a bug or an omission on Evan You's part, since the spec explicitly allows it . I've filed an issue report about it. If you're really concerned with current TS annotations, just use the equivalent this.$router.go(0)

As to 'why is it so': go internally passes its arguments to window.history.go , so its equal to windows.history.go() - which, in turn, reloads the page, as per MDN doc .

note: since this executes a "soft" reload on regular desktop (non-portable) Firefox, a bunch of strange quirks may appear if you use it but in fact you require a true reload; using the window.location.reload(true); ( https://developer.mozilla.org/en-US/docs/Web/API/Location/reload ) mentioned by OP instead may help - it certainly did solve my problems on FF.

The simplest solution is to add a :key attribute to :

<router-view :key="$route.fullPath"></router-view>

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.

this.$router.go(this.$router.currentRoute)

Vue-Router Docs:

I checked vue-router repo on GitHub and it seems that there isn't reload() method any more. But in the same file, there is: currentRoute object.

Source: vue-router/src/index.js
Docs: docs

get currentRoute (): ?Route {
    return this.history && this.history.current
  }

Now you can use this.$router.go(this.$router.currentRoute) for reload current route.

Simple example .

Version for this answer:

"vue": "^2.1.0",
"vue-router": "^2.1.1"

如果您使用 Typescript,请使用router.go(0) ,它会询问 go 方法的参数。

router.js

routes: [
{
  path: '/',
  component: test,
  meta: {
    reload: true,
  },
}]

main.js

import router from './router';

new Vue({
  render: h => h(App),
  router,
  watch:{
    '$route' (to) {
       if(to.currentRoute.meta.reload==true){window.location.reload()}
  }
}).$mount('#app')

Resolve the route to a URL and navigate the window with Javascript.

 let r = this.$router.resolve({ name: this.$route.name, // put your route information in params: this.$route.params, // put your route information in query: this.$route.query // put your route information in }); window.location.assign(r.href)

This method replaces the URL and causes the page to do a full request (refresh) rather than relying on Vue.router. $router.go does not work the same for me even though it is theoretically supposed to.

`<router-link :to='`/products`' @click.native="$router.go()" class="sub-link"></router-link>`

我已经尝试过重新加载当前页面。

It's my reload. Because of some browser very weird. location.reload can't reload.

methods:{
   reload: function(){
      this.isRouterAlive = false
      setTimeout(()=>{
         this.isRouterAlive = true
      },0)
   }
}
<router-view v-if="isRouterAlive"/>

Here's a solution if you just want to update certain components on a page:

In template

<Component1 :key="forceReload" />
<Component2 :key="forceReload" />

In data

data() {
  return {
    forceReload: 0
  {
}

In methods:

   Methods: {
     reload() {
        this.forceReload += 1
     }
   }

Use a unique key and bind it to a data property for each one you want to update (I typically only need this for a single component, two at the most. If you need more, I suggest just refreshing the full page using the other answers.

I learned this from Michael Thiessen's post: https://medium.com/hackernoon/the-correct-way-to-force-vue-to-re-render-a-component-bde2caae34ad

function removeHash () { 
    history.pushState("", document.title, window.location.pathname
                                          + window.location.search);
}


App.$router.replace({name:"my-route", hash: '#update'})
App.$router.replace({name:"my-route", hash: ' ', params: {a: 100} })
setTimeout(removeHash, 0)

Notes:

  1. And the # must have some value after it.
  2. The second route hash is a space, not empty string.
  3. setTimeout , not $nextTick to keep the url clean.

For rerender you can use in parent component

<template>
  <div v-if="renderComponent">content</div>
</template>
<script>
export default {
   data() {
      return {
        renderComponent: true,
      };
    },
    methods: {
      forceRerender() {
        // Remove my-component from the DOM
        this.renderComponent = false;

        this.$nextTick(() => {
          // Add the component back in
          this.renderComponent = true;
        });
      }
    }
}
</script>

Sep, 2021 Update:

You can force-reload components by adding :key="$route.fullPath" .

For Child Component:

<Child :key="$route.fullPath" />

For router-view tag:

<router-view :key="$route.fullPath" />

However, :key="$route.fullPath" only can force-reload the components of the different route but not the components of the same route. To be able to force-reload the components of the same route as well, we need to add a value to :key= and change the value.

*We can assign Array to :key= .

<template>
  <Child 
    :key="[$route.fullPath, value]" // Can assign "Array" to ":key="
    @childReload="reload" // Call @click="$emit('childReload')" in   
  />                      // Child Component to increment the value.
</template> 

    OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR

<template>
  <router-view 
    :key="[$route.fullPath, value]" // Can assign "Array" to ":key="
    @routerViewReload="reload" // Call @click="$emit('routerViewReload')"
  />                           // in Child Component to increment the value.
</template>
    
<script>
export default {
  name: "Parent", components: { Child, },
  data() {
    return {
      value: 0,
    };
  },
  methods: {
    reload() {
      this.value++;
    }
  }
}
</script>

However, to keep using both $route.fullPath and value causes some error sometimes so only when some event like Click happens, we use both $route.fullPath and value . Except when some event like Click happens, we always need to use only $route.fullPath .

This is the final code:

<template>
  <Child 
    :key="state ? $route.fullPath : [$route.fullPath, value]"
    @childReload="reload" // Call @click="$emit('childReload')" in
  />                      // Child Component to increment the value.
</template>
    
    OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR
    
<template>
  <router-view 
    :key="state ? $route.fullPath : [$route.fullPath, value]"
    @routerViewReload="reload" // Call @click="$emit('routerViewReload')" in
  />                           // Child Component to increment the value.
</template>
        
<script>
export default {
  name: "Parent", components: { Child, },
  data() {
    return {
      state: true,
      value: 0,
    };
  },
  methods: {
    reload() {
      this.state = false;
      this.value++;
      this.$nextTick(() => this.state = true);
    }
  }
}
</script>

Unfortunately, there are no simple ways to force-reload components properly in Vue. That's the problem of Vue which is needed to solve.

Simple reload/refresh any component do below things

<ProductGrid v-if="renderComponent"/>

<script>
import ProductGrid from "./product-grid";
export default {
  name:'product',
  components: {
    ProductGrid
  },
  data() {
    return {
      renderComponent: true,
    };
  },
  methods: {
    forceRerender: function() {
      // Remove my-component from the DOM
        this.renderComponent = false;
        this.$nextTick(() => {
            // Add the component back in
            this.renderComponent = true;
        });
    }
 },
 watch:{
    '$route.query.cid'(newId, oldId) {
        if(newId>0){
            this.forceRerender();
        }      
     }
  }
}
</script>

This is how i do it!

methods:
{
        reload()
        {
            var location = this.$route.fullPath

            this.$router.replace('/')

            this.$nextTick(() => this.$router.replace(location))
        }
}

Found a way to go to reload same route from same source on vue router 4:

import {
  useRouter,
  NavigationFailureType,
  isNavigationFailure,
} from "vue-router";

const router = useRouter();
const handleLinkClick = (link) => {
  router.push({ name: link }).then((failure) => {
    if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
      router.go({ name: link });
    }
  });

source

This answer helped me:

 this.$router
          .push({ path: '/home' })
          .then(() => { this.$router.go() })

It first redirects to /home and then reloads the page. Helps with getting updated navbar after login.

vueObject.$forceUpdate();

为什么不使用 forceUpdate 方法?

window.location.reload();

You can use it to reload your current page. There is similar usage in Jquery too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM