Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] A reload method like location.reload() #296

Closed
fnlctrl opened this issue Dec 18, 2015 · 64 comments
Closed

[Feature] A reload method like location.reload() #296

fnlctrl opened this issue Dec 18, 2015 · 64 comments

Comments

@fnlctrl
Copy link
Member

fnlctrl commented Dec 18, 2015

I have a router-view that needs to be reloaded after sending some POST requests and receiving whether the operation was successful, but

this.$route.router.go(this.$route.path)

doesn't trigger a reload even if the component's route.canReuse is set to false.

Now I can only do

created.apply(this) // `created` is the life-cycle hook function for the component

in the ajax callback to force the router-view to update itself, which is cumbersome.

Perhaps something like $route.router.reload() would be great, as it would be the counterpart of location.reload().

@fnlctrl
Copy link
Member Author

fnlctrl commented Dec 23, 2015

Lacking a reload method also prevents me from putting request promises in component.route.data() because it's only triggered when route path changes... If I do so, I'd have to write the same request promises again in another reload method..

@roblav96
Copy link

Having a reload route method would be nice.

@ccqgithub
Copy link

i think so ~~ Having a reload route method would be nice.

@roblav96
Copy link

roblav96 commented Jan 7, 2016

having a force re-render on a specific v-for item would be even better

@amirrustam
Copy link

@fnlctrl can you please elaborate in detail on your particular use case for this feature? I'm finding it difficult to reason why the entire router-view needs to be reloaded based on a status of a POST request.

@yyx990803
Copy link
Member

Here's what I think: after the POST request, what you really want to do is not reloading the component, but rather re-fetch the data. However you have placed the data-fetching logic in your component's lifecycle hooks, but that doesn't have to be the case. Consider:

export default {
  created () {
    this.fetchData()
  },
  methods: {
    fetchData () {
       // fetch data
    }
  }
}

After the POST request is resolved, you simply call this.fetchData() to re-fetch. Reloading the entire component is doing more than necessary, since it leads to a full re-render of the DOM as well.

@fnlctrl
Copy link
Member Author

fnlctrl commented Jan 14, 2016

@yyx990803 No that's not what I meant..
I just want to reload the route, and the component is reused (route.canReuse is true), so nothing is changed except for it's route.data() called again. No expensive dom operations. (I really want to use route.data because it's so elegant).

Consider this.

route: {
    data: ({to: {params: {someParam}}}) => ({
        foo: $.get('/path/to/resource', {someParam}),
    })
}

Now, without a reload method, I will have to write$.get('/path/to/resource', {someParam}) again in fetchData..

@fnlctrl
Copy link
Member Author

fnlctrl commented Jan 14, 2016

It's like when it transitions from /a/1 to /a/2, the component is reused, only the route.data() is fired again.
Now I just want the same thing to happen when transitioning from /a/1 to /a/1 (explicitly, with a reload method).

@yyx990803
Copy link
Member

Hmm that makes sense, maybe a $reloadRouteData() method?

@fnlctrl
Copy link
Member Author

fnlctrl commented Jan 14, 2016

Looks good!
Well, since canReuse is about to be deprecated and every component will be reusable (#321), I think $reload would suffice since nothing else will be fired again except for route.data()?

@yyx990803
Copy link
Member

On another thought, it might be more straightforward to just add an additional option to router.go:

router.go({
  path: '/a/1',
  force: true
})

Then it will force the router to match the route even if it is the same with current route, and because all current components can be reused, only data hooks will re-run.

@yyx990803 yyx990803 reopened this Jan 15, 2016
@rpkilby
Copy link

rpkilby commented Jan 15, 2016

@yyx990803 In addition to the force option, would it make sense to add a $reload function that simply calls router.go with the correct arguments? The router.go call doesn't intuitively read as a reload operation to me.

@fnlctrl
Copy link
Member Author

fnlctrl commented Jan 17, 2016

Adding both would be nice, but in what scenario other than reloading would I use force option?

@azamat-sharapov
Copy link

@coulix did you try data hook?

@simplesmiler
Copy link
Member

I have a use case for this, and it was already mentioned by @liudangyi: #311 (comment)

Another reason why I need a "refresh" function: we use a beforeEach hook to check authentication. When a user logs in / logs out, we need to trigger this hook again to make sure he has the right to see this page.

@stephanedemotte
Copy link

any news about the force option ? :)

@altitudems
Copy link

Also interested in this feature.

@mrgodhani
Copy link

+1 for this feature too.

@happilymarrieddad
Copy link

+1 this feature!!!

@yocheved
Copy link

I would love this feature too!

@fer-ri
Copy link

fer-ri commented Jun 13, 2016

force: true would be useful :)

@happilymarrieddad
Copy link

+1 this feature!!! It sounds like there is something like this already in place??? Can someone please confirm if that is the case. Thanks!

@ianberdin
Copy link

+1
Why so long? :(

@fritx
Copy link

fritx commented Oct 11, 2017

'Joshwoooooooooooooooooooooooooooooooong'.length
>> 39

@davodaslanifakor
Copy link

@Joshwoooooooooooooooooooooooooooooooong
how use that please full example

@zongzheng123
Copy link

what is my problem encountered is that i initialize my data with the property 'data',and i what to rerender them,how can i do

@aweiu
Copy link

aweiu commented Jan 10, 2018

Use v-if to control the router-view to implement a reload method in the root component APP.vue

<template>
  <router-view v-if="isRouterAlive"/>
</template>
<script>
export default {
 data () {
   return {
     isRouterAlive: true
   }
 },
 methods: {
   reload () {
     this.isRouterAlive = false
     this.$nextTick(() => (this.isRouterAlive = true))
   }   
 }
}
</script>

Then any other want to refresh their own routing page, you can do this:

this.$root.reload()

If the $root is not router container,please use provide / inject to do this.知乎上我写了个完整版本的

@8gua-men
Copy link

8gua-men commented Jan 10, 2018

VueRouter.prototype.reload = ->
    history = @history
    current = history.current
    history.updateRoute {matched:[], path:""}
    @replace current
    return

@happilymarrieddad
Copy link

I like the above solution! +1

@FrEaKmAn
Copy link

FrEaKmAn commented Jan 12, 2018

It would make sense to add this also to router-link. In our case it's useful to perform some action (like hide dropdown) if route changes using watch: $route. This doesn't work if router route is already active and I would like to avoid additional ifs

@pablich
Copy link

pablich commented Jan 15, 2018

My solution to refresh the component without reloading the url:

router/index.js
{ path: 'Redirect/:path', name: 'Redirect', component: Redirect, meta: { requiresAuth: true }, },

components/shared/Redirect.vue
export default { beforeCreate() { const path = this.$route.params.path; this.$router.push('/'); this.$router.push(path); }, };

The action that trigger the refresh:
this.$router.push(Redirect${this.$route.path});

@kokokele
Copy link

watch: {
$route (data, oldData) {
this.reInit()
},
// ...
},

that watch not call

@kokokele
Copy link

kokokele commented Mar 28, 2018

in vue-router3.0, it's work.

 this.$router.push({
                    name: 'path_key',
             
                    query: {
                        t: + new Date()
                    },
      
                    
                });

@bublikOff
Copy link

bublikOff commented Apr 6, 2018

Here is my workaround to reload route without full page reload

var vueRouteReloader = Vue.extend(
{
	template: '<div/>',
	mounted: function()
	{
		setTimeout(function() { router.back(); }, 100);
	}
});

and then just call

router.push('/reload');

this method does not reload page at all and does not change variables value and I dont have to use session storage and restore it on page reload
PS
I do use a splashscreen while walking between routes. So when I use "reload" route it seamless for users

@jakeg
Copy link

jakeg commented Aug 2, 2018

Here's my solution, which I use for links in a header, which when clicked should load a page or refresh it (scrolling to the top) if you're already on it.

Add ?refresh to any links that you want to work like this, such as <router-link to="/path/to?refresh">click me</router-link> or router.push('/path/to?refresh')

Now in your page component add this:

beforeRouteUpdate (to, from, next) {
  next() // IMPORTANT: *after* next() else the ?refresh sticks around half the time
  this.checkRefresh()
},
created () {
  this.checkRefresh()
},
methods: {
  checkRefresh () {
    // ?refresh to force refresh if clicking eg the icon/button in the header menu
    // we make sure it doesn't stick around in the url bar for the user
    if (this.$route.query.refresh !== undefined) {
      this.loaded = false
      this.$router.replace(this.$route.path)
    } else {
      this.fetchData()
    }
  },
  fetchData () {
    // ... anything you want to happen on create or update
  }
}

@meetyourmm
Copy link

那不需要重新渲染页面改怎么办?我现在有个对话列表页面,类似qq。现在每次切换回来,页面被刷新了,我现在不需要刷新,该怎么写?

@meetyourmm
Copy link

I now have a conversation list page, similar to qq. Now every time I switch back, the page is refreshed. I don't need to refresh now. How to do?

@nanlei2000
Copy link

nanlei2000 commented Nov 22, 2018

here is my solution:
create a relaod.vue and give it a route name reload :

<template> 
  <div></div>
</template>
<script>
export default {
  created() {
    this.$router.push(this.$route.query.path)
  }
}
</script>

then :

const path = xxx
this.$router.push({ name: 'reload', query: { path } })

the relaod.vue should be the child of the basic layout component in order to prevent the whole page refreshing.

@luisjoserivera
Copy link

Here is my solution to apply the refresh either while entering or leaving a page that requires a refresh. I do it like this because most of the time I require a page refresh is because I'm adding page specific content from outside of Vue (in my case via PHP) and I needed a way to get rid of it after leaving the route.

export const router = new Router({
  routes: [
    {
      path: "/first",
      name: "first",
      component: First
    },
    {
      path: "/second",
      name: "second",
      component: Second,
      meta: {
        refresh: true
      }
    }
  ]
});

router.beforeEach((to, from, next) => {
  // If we are going to a page that requires a refresh
  // null is used to avoid an infinite refresh loop
  if (to.meta.refresh && from.name !== null) {
    window.location.href = to.path;
    return;
  }
  // If we are leaving a page that required a refresh
  if (from.meta.refresh) {
    window.location.href = to.path;
    return;
  }
  next();
});

Hope it may be useful for someone.

@gaopengpian
Copy link

@happierall The author is busy :D
You can use

$router.go({
    path: $router.path,
    query: {
        t: + new Date()
    }
})

for now, to simulate a reload

this will reload whole page

@loic-roux-404
Copy link

loic-roux-404 commented May 28, 2019

I have actually found a pretty good solution using async function
I have also axios requests in my app components and the good point is these requests don't load anymore when i'm not logged.

//all router request (load, page change...)
router.beforeEach(async(to, from, next) => {
    console.log(await store.state.security.isAuthenticated);

    if (to.matched.some(record => record.meta.requiresAuth)) {
        // this route requires auth, check if logged in
        // if not, redirect to login page.


       //check auth in vuex store (also work with getters)
        if (store.state.security.isAuthenticated) {
            next();
        } else {
            next({
                path:'/home',
                query:{redirect:to.fullPath},//still useful when not logged in

            });
            await this.$router.go({
                path:to.fullPath,
                force:true
            })
        }
    }else {
        next(); // make sure to always call next()!
    }
}

No infinite loop at all, hope i can help...

@seongjin605
Copy link

thanks :)

@farwish
Copy link

farwish commented Nov 25, 2019

@hypo1986
Copy link

有一个最简单粗暴的办法解决此问题:组件的name 值设置跟路由菜单里边的 name 只有不一样,每次重新点击菜单,就好重新渲染加载api 哈哈

@zichen1019
Copy link

reload method

const route = {
  path: this.$route.path.toString(),
  name: this.$route.name.toString(),
  query: this.deepCopy(this.$route.query),
  params: this.deepCopy(this.$route.params)
}
// 重点在这
new Promise(resolve => {
  this.$router.push({ path: '/' })
  resolve()
}).then(() => {
  this.$router.push(route)
})

deepcopy method

function deepCopy(o) {
  if (o instanceof Array) {
    var n = []
    for (var i = 0; i < o.length; ++i) {
      n[i] = this.deepCopy(o[i])
    }
    return n
  } else if (o instanceof Object) {
    var nn = {}
    for (var j in o) {
      nn[j] = this.deepCopy(o[j])
    }
    return nn
  } else {
    return o
  }
}

@BalanaguYashwanth
Copy link

we can use forms also in some cases to realod the page

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests