Vue.js: Using beforeRouteLeave in a sub-component of a route

by Mani Jagadeesan

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-router.js"></script>
<body>
    <div id="app">
        <div>My App Header, navbar</div>
        <router-view></router-view>
    </div>
</body>

CSS

body {
    margin: 20px;
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

JavaScript

const HomeComponent = Vue.component('home', {
    template: `
        <div>
            <p>This is my home route</p>
            <router-link :to="{name: 'another-route'}">To Another Route</router-link>
        </div>`,
    mounted: function() {
        console.log("In HomeComponent")
    }
});

const AnotherComponent = Vue.component('another', {
    template: `
        <div>
            <p>This is my another-route with a sub-component below that has a timer function</p>
            <sub-component ref="mySubComponent"></sub-component>
            <router-link :to="{name: 'home'}">Home</router-link>
        </div>`,
    mounted: function() {
        console.log("In AnotherComponent")
    },
    beforeRouteLeave: function(to, from, next) {
        console.log("In beforeRouteLeave of AnotherComponent")
        // Indicate to the SubComponent that we are leaving the route
        this.$refs.mySubComponent.prepareToExit();
        // Make sure to always call the next function, otherwise the hook will never be resolved
        // Ref: https://router.vuejs.org/en/advanced/navigation-guards.html
        next();
    }
});

const SubComponent = Vue.component('sub-component', {
    template: `
        <div>
            <p>This is my sub-component with a timer</p>
        </div>`,
    data: function() {
        return {
            counter: 0,
            twoSecondsTimerEvents: null  // This will be initialized in mounted hook
        }
    },
    mounted: function() {
        console.log("In SubComponent, starting 'twoSecondsTimerEvents'")
        this.twoSecondsTimerEvents = setInterval(() => {
            this.counter++;
            console.log("Timer event, counter: " + this.counter);
        }, 2000)
    },
    methods: {
        prepareToExit: function() {
            console.log("Preparing to exit sub component, stopping 'twoSecondsTimerEvents'")
            clearInterval(this.twoSecondsTimerEvents)
        }
    }
});

const ROUTES = new VueRouter({
    routes: [{
  ...