Vuejs: Event on route change

Viewed 217460

On my main page I have dropdowns that show v-show=show by clicking on the link @click = "show=!show" and I want to set show=false when I change the route. Please advise me on how to realize this thing.

8 Answers

Setup a watcher on the $route in your component like this:

watch:{
    $route (to, from){
        this.show = false;
    }
} 

This observes for route changes and when changed ,sets show to false

Just in case anyone is looking for how to do it in Typescript, here is the solution:

@Watch('$route', { immediate: true, deep: true })
onUrlChange(newVal: Route) {
    // Some action
}

And yes as mentioned by @Coops below, please do not forget to include :

import { Watch } from 'vue-property-decorator';

Edit: Alcalyn made a very good point of using Route type instead of using any:

import { Watch } from 'vue-property-decorator';    
import { Route } from 'vue-router';

Watcher with the deep option didn't work for me.

Instead, I use updated() lifecycle hook which gets executed everytime the component's data changes. Just use it like you do with mounted().

mounted() {
   /* to be executed when mounted */
},
updated() {
   console.log(this.$route)
}

For your reference, visit the documentation.

UPDATE

As stated by @CHANist, router.listen no longer works, I don't know from which version it stopped working, but the good news (as also stated by @CHANist) is we can use:

this.$router.history.listen((newLocation) => {console.log(newLocation);})

OLD Response

The above responses are the better, but just for completeness, when you are in a component you can access the history object inside the VueRouter with: this.$router.history. That means we can listen to changes with:

this.$router.listen((newLocation) => {console.log(newLocation);})

I think this is mainly useful when used along with this.$router.currentRoute.path You can check what I am talking about placing a debugger

instruction in your code and begin playing with the Chrome DevTools Console.

import { useRouter } from "vue-router";

const router = useRouter();

router.afterEach((to, from) => { });

Another solution for typescript user:

import Vue from "vue";
import Component from "vue-class-component";

@Component({
  beforeRouteLeave(to, from, next) {
    // incase if you want to access `this`
    // const self = this as any;
    next();
  }
})

export default class ComponentName extends Vue {}

using Vue Router is an alternative way, use the beforeRouteLeave after methods in your component like this:

<template>
   <button @click="ShowMethod">DisplayButton</button>
</template>
<script>
  data() {
    return { show: true };
   },
   methods: {
   ShowMethod() {
   this.show = false;
    }
   },
   beforeRouteLeave(to, from, next) {
   this.show = false;
   next();
 }
</script>

according to VueJs documentation, it's called Navigation Guards check the link below:

Navigation Guards

The leave guard is usually used to prevent the user from accidentally leaving the route with unsaved edits. The navigation can be canceled by calling

In-Component Guards:

beforeRouteEnter

beforeRouteUpdate

beforeRouteLeave

  beforeRouteLeave(to, from, next) {
// called when the route that renders this component is about to
// be navigated away from.
// has access to `this` component instance.
 }

look at the below link for more information:

In-Component Guards

Related