BeforeRouteUpdate or Leave does not react in single file component











up vote
1
down vote

favorite












<template>
<div>
<top-loader ref="topLoader"></top-loader>
<div class="container">
<router-view></router-view>
</div>
</div>
</template>

<script>
import Toploader from '../global/Toploader.vue';
export default {
components: {
'top-loader': Toploader,
},
mounted () {
this.$refs.topLoader.start();
setTimeout(() => {
this.$refs.topLoader.done();
}, 2000)
//works here
},
beforeRouteUpdate (to, from, next) {
this.$refs.topLoader.done();
console.log(to);//not even this
next();
},
beforeRouteLeave (to, from, next) {
this.$refs.topLoader.start();
console.log(to);//not even this
next();
}
};
</script>


This is my single file component that is called in app.js:



require('./scripts/bootstrap');

window.Vue = require('vue');
import SFC from './components/SFC.vue'
import Routes from './routes/routes'
import VueRouter from 'vue-router'


Vue.use(VueRouter);

const router = new VueRouter({routes: Routes, mode: 'history'});

const app = new Vue({
el: '#root',
render: h => h(SFC),
router: router
});


I have 3 routes ('/', '/about', '/contact') inside routes file..
Nothing works with beforeRouteUpdate or Leave, but just if I add watcher for $route it does work...



Like this:



watch: {
$route(to, from) {
console.log('after', this.$route.path);
}
}


But this fires after route is loaded, I need one before it leaves current route and one after it load next route.



Any help?










share|improve this question




























    up vote
    1
    down vote

    favorite












    <template>
    <div>
    <top-loader ref="topLoader"></top-loader>
    <div class="container">
    <router-view></router-view>
    </div>
    </div>
    </template>

    <script>
    import Toploader from '../global/Toploader.vue';
    export default {
    components: {
    'top-loader': Toploader,
    },
    mounted () {
    this.$refs.topLoader.start();
    setTimeout(() => {
    this.$refs.topLoader.done();
    }, 2000)
    //works here
    },
    beforeRouteUpdate (to, from, next) {
    this.$refs.topLoader.done();
    console.log(to);//not even this
    next();
    },
    beforeRouteLeave (to, from, next) {
    this.$refs.topLoader.start();
    console.log(to);//not even this
    next();
    }
    };
    </script>


    This is my single file component that is called in app.js:



    require('./scripts/bootstrap');

    window.Vue = require('vue');
    import SFC from './components/SFC.vue'
    import Routes from './routes/routes'
    import VueRouter from 'vue-router'


    Vue.use(VueRouter);

    const router = new VueRouter({routes: Routes, mode: 'history'});

    const app = new Vue({
    el: '#root',
    render: h => h(SFC),
    router: router
    });


    I have 3 routes ('/', '/about', '/contact') inside routes file..
    Nothing works with beforeRouteUpdate or Leave, but just if I add watcher for $route it does work...



    Like this:



    watch: {
    $route(to, from) {
    console.log('after', this.$route.path);
    }
    }


    But this fires after route is loaded, I need one before it leaves current route and one after it load next route.



    Any help?










    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      <template>
      <div>
      <top-loader ref="topLoader"></top-loader>
      <div class="container">
      <router-view></router-view>
      </div>
      </div>
      </template>

      <script>
      import Toploader from '../global/Toploader.vue';
      export default {
      components: {
      'top-loader': Toploader,
      },
      mounted () {
      this.$refs.topLoader.start();
      setTimeout(() => {
      this.$refs.topLoader.done();
      }, 2000)
      //works here
      },
      beforeRouteUpdate (to, from, next) {
      this.$refs.topLoader.done();
      console.log(to);//not even this
      next();
      },
      beforeRouteLeave (to, from, next) {
      this.$refs.topLoader.start();
      console.log(to);//not even this
      next();
      }
      };
      </script>


      This is my single file component that is called in app.js:



      require('./scripts/bootstrap');

      window.Vue = require('vue');
      import SFC from './components/SFC.vue'
      import Routes from './routes/routes'
      import VueRouter from 'vue-router'


      Vue.use(VueRouter);

      const router = new VueRouter({routes: Routes, mode: 'history'});

      const app = new Vue({
      el: '#root',
      render: h => h(SFC),
      router: router
      });


      I have 3 routes ('/', '/about', '/contact') inside routes file..
      Nothing works with beforeRouteUpdate or Leave, but just if I add watcher for $route it does work...



      Like this:



      watch: {
      $route(to, from) {
      console.log('after', this.$route.path);
      }
      }


      But this fires after route is loaded, I need one before it leaves current route and one after it load next route.



      Any help?










      share|improve this question















      <template>
      <div>
      <top-loader ref="topLoader"></top-loader>
      <div class="container">
      <router-view></router-view>
      </div>
      </div>
      </template>

      <script>
      import Toploader from '../global/Toploader.vue';
      export default {
      components: {
      'top-loader': Toploader,
      },
      mounted () {
      this.$refs.topLoader.start();
      setTimeout(() => {
      this.$refs.topLoader.done();
      }, 2000)
      //works here
      },
      beforeRouteUpdate (to, from, next) {
      this.$refs.topLoader.done();
      console.log(to);//not even this
      next();
      },
      beforeRouteLeave (to, from, next) {
      this.$refs.topLoader.start();
      console.log(to);//not even this
      next();
      }
      };
      </script>


      This is my single file component that is called in app.js:



      require('./scripts/bootstrap');

      window.Vue = require('vue');
      import SFC from './components/SFC.vue'
      import Routes from './routes/routes'
      import VueRouter from 'vue-router'


      Vue.use(VueRouter);

      const router = new VueRouter({routes: Routes, mode: 'history'});

      const app = new Vue({
      el: '#root',
      render: h => h(SFC),
      router: router
      });


      I have 3 routes ('/', '/about', '/contact') inside routes file..
      Nothing works with beforeRouteUpdate or Leave, but just if I add watcher for $route it does work...



      Like this:



      watch: {
      $route(to, from) {
      console.log('after', this.$route.path);
      }
      }


      But this fires after route is loaded, I need one before it leaves current route and one after it load next route.



      Any help?







      vue.js vuejs2 vue-component vue-router






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 23:32

























      asked Nov 10 at 23:22









      Learner

      52512




      52512
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          It works as expected.



          Referring to vue-router documentation about In-Component Navigation Guards:




          called before the route that renders this component is confirmed.




          Meaning, that when navigation guards are declared inside component, they will be triggered only when render of that component happens. Not nested components, as in code example above, because SFC.vue is never unmounted.



          You can achieve desired behavior by:





          1. watch-ing route changes from parent component, as in example code you provided. The downside is that it will be triggered on any(!) route change. If navigation occurs inside nested components - it will be triggered. The benefit - this approach has access to component instance (this).

          2. With Global Guards declared on router instance. Again, it will be triggered on every route change, so you will have to verify if it is a child route of those you should handle.

          3. By declaring a handler function and adding it to each route configuration as in code example. Good thing is that you can reuse handler functions and keep them in a separate module, while importing inside router instance constructor.

          4. Move existing handlers into a mixin and using it inside component declaration of each route that should be handled.






          share|improve this answer





















          • How can I access refs from vue instance component within global guards, I keep getting undefined...
            – Learner
            Nov 11 at 1:45










          • You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
            – aBiscuit
            Nov 11 at 2:14








          • 1




            I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
            – Learner
            Nov 11 at 2:27






          • 1




            I found better answer :D Which works :D
            – Learner
            Nov 11 at 11:40


















          up vote
          0
          down vote













          After good sleep I found answer:



          I made:



          window.Event = new class {
          constructor() {
          this.vue = new Vue();
          }

          fire(event, data = null) {
          this.vue.$emit(event, data);
          }

          listen(event, callback) {
          this.vue.$on(event, callback);
          }
          };

          const router = new VueRouter({routes: Routes, mode: 'history'});

          router.beforeEach((to, from, next) => {
          Event.fire('loader-start', 'start');
          next();
          });

          router.afterEach((to, from) => {
          setTimeout(function() {
          Event.fire('loader-done', 'done');
          }, 500);
          });


          And inside component I listen for those events and change the $ref :D






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244391%2fbeforerouteupdate-or-leave-does-not-react-in-single-file-component%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            It works as expected.



            Referring to vue-router documentation about In-Component Navigation Guards:




            called before the route that renders this component is confirmed.




            Meaning, that when navigation guards are declared inside component, they will be triggered only when render of that component happens. Not nested components, as in code example above, because SFC.vue is never unmounted.



            You can achieve desired behavior by:





            1. watch-ing route changes from parent component, as in example code you provided. The downside is that it will be triggered on any(!) route change. If navigation occurs inside nested components - it will be triggered. The benefit - this approach has access to component instance (this).

            2. With Global Guards declared on router instance. Again, it will be triggered on every route change, so you will have to verify if it is a child route of those you should handle.

            3. By declaring a handler function and adding it to each route configuration as in code example. Good thing is that you can reuse handler functions and keep them in a separate module, while importing inside router instance constructor.

            4. Move existing handlers into a mixin and using it inside component declaration of each route that should be handled.






            share|improve this answer





















            • How can I access refs from vue instance component within global guards, I keep getting undefined...
              – Learner
              Nov 11 at 1:45










            • You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
              – aBiscuit
              Nov 11 at 2:14








            • 1




              I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
              – Learner
              Nov 11 at 2:27






            • 1




              I found better answer :D Which works :D
              – Learner
              Nov 11 at 11:40















            up vote
            0
            down vote













            It works as expected.



            Referring to vue-router documentation about In-Component Navigation Guards:




            called before the route that renders this component is confirmed.




            Meaning, that when navigation guards are declared inside component, they will be triggered only when render of that component happens. Not nested components, as in code example above, because SFC.vue is never unmounted.



            You can achieve desired behavior by:





            1. watch-ing route changes from parent component, as in example code you provided. The downside is that it will be triggered on any(!) route change. If navigation occurs inside nested components - it will be triggered. The benefit - this approach has access to component instance (this).

            2. With Global Guards declared on router instance. Again, it will be triggered on every route change, so you will have to verify if it is a child route of those you should handle.

            3. By declaring a handler function and adding it to each route configuration as in code example. Good thing is that you can reuse handler functions and keep them in a separate module, while importing inside router instance constructor.

            4. Move existing handlers into a mixin and using it inside component declaration of each route that should be handled.






            share|improve this answer





















            • How can I access refs from vue instance component within global guards, I keep getting undefined...
              – Learner
              Nov 11 at 1:45










            • You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
              – aBiscuit
              Nov 11 at 2:14








            • 1




              I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
              – Learner
              Nov 11 at 2:27






            • 1




              I found better answer :D Which works :D
              – Learner
              Nov 11 at 11:40













            up vote
            0
            down vote










            up vote
            0
            down vote









            It works as expected.



            Referring to vue-router documentation about In-Component Navigation Guards:




            called before the route that renders this component is confirmed.




            Meaning, that when navigation guards are declared inside component, they will be triggered only when render of that component happens. Not nested components, as in code example above, because SFC.vue is never unmounted.



            You can achieve desired behavior by:





            1. watch-ing route changes from parent component, as in example code you provided. The downside is that it will be triggered on any(!) route change. If navigation occurs inside nested components - it will be triggered. The benefit - this approach has access to component instance (this).

            2. With Global Guards declared on router instance. Again, it will be triggered on every route change, so you will have to verify if it is a child route of those you should handle.

            3. By declaring a handler function and adding it to each route configuration as in code example. Good thing is that you can reuse handler functions and keep them in a separate module, while importing inside router instance constructor.

            4. Move existing handlers into a mixin and using it inside component declaration of each route that should be handled.






            share|improve this answer












            It works as expected.



            Referring to vue-router documentation about In-Component Navigation Guards:




            called before the route that renders this component is confirmed.




            Meaning, that when navigation guards are declared inside component, they will be triggered only when render of that component happens. Not nested components, as in code example above, because SFC.vue is never unmounted.



            You can achieve desired behavior by:





            1. watch-ing route changes from parent component, as in example code you provided. The downside is that it will be triggered on any(!) route change. If navigation occurs inside nested components - it will be triggered. The benefit - this approach has access to component instance (this).

            2. With Global Guards declared on router instance. Again, it will be triggered on every route change, so you will have to verify if it is a child route of those you should handle.

            3. By declaring a handler function and adding it to each route configuration as in code example. Good thing is that you can reuse handler functions and keep them in a separate module, while importing inside router instance constructor.

            4. Move existing handlers into a mixin and using it inside component declaration of each route that should be handled.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 11 at 1:38









            aBiscuit

            1,2671513




            1,2671513












            • How can I access refs from vue instance component within global guards, I keep getting undefined...
              – Learner
              Nov 11 at 1:45










            • You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
              – aBiscuit
              Nov 11 at 2:14








            • 1




              I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
              – Learner
              Nov 11 at 2:27






            • 1




              I found better answer :D Which works :D
              – Learner
              Nov 11 at 11:40


















            • How can I access refs from vue instance component within global guards, I keep getting undefined...
              – Learner
              Nov 11 at 1:45










            • You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
              – aBiscuit
              Nov 11 at 2:14








            • 1




              I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
              – Learner
              Nov 11 at 2:27






            • 1




              I found better answer :D Which works :D
              – Learner
              Nov 11 at 11:40
















            How can I access refs from vue instance component within global guards, I keep getting undefined...
            – Learner
            Nov 11 at 1:45




            How can I access refs from vue instance component within global guards, I keep getting undefined...
            – Learner
            Nov 11 at 1:45












            You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
            – aBiscuit
            Nov 11 at 2:14






            You can't. Global router guards do not receive component's instance as arguments, only Route object. Only way to access $refs is inside component and only after mounted hook.
            – aBiscuit
            Nov 11 at 2:14






            1




            1




            I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
            – Learner
            Nov 11 at 2:27




            I found out that I can use this.$router. from component for done and maybe i can start by adding native click event to route link, i am dead now will try after few hours of sleep
            – Learner
            Nov 11 at 2:27




            1




            1




            I found better answer :D Which works :D
            – Learner
            Nov 11 at 11:40




            I found better answer :D Which works :D
            – Learner
            Nov 11 at 11:40












            up vote
            0
            down vote













            After good sleep I found answer:



            I made:



            window.Event = new class {
            constructor() {
            this.vue = new Vue();
            }

            fire(event, data = null) {
            this.vue.$emit(event, data);
            }

            listen(event, callback) {
            this.vue.$on(event, callback);
            }
            };

            const router = new VueRouter({routes: Routes, mode: 'history'});

            router.beforeEach((to, from, next) => {
            Event.fire('loader-start', 'start');
            next();
            });

            router.afterEach((to, from) => {
            setTimeout(function() {
            Event.fire('loader-done', 'done');
            }, 500);
            });


            And inside component I listen for those events and change the $ref :D






            share|improve this answer

























              up vote
              0
              down vote













              After good sleep I found answer:



              I made:



              window.Event = new class {
              constructor() {
              this.vue = new Vue();
              }

              fire(event, data = null) {
              this.vue.$emit(event, data);
              }

              listen(event, callback) {
              this.vue.$on(event, callback);
              }
              };

              const router = new VueRouter({routes: Routes, mode: 'history'});

              router.beforeEach((to, from, next) => {
              Event.fire('loader-start', 'start');
              next();
              });

              router.afterEach((to, from) => {
              setTimeout(function() {
              Event.fire('loader-done', 'done');
              }, 500);
              });


              And inside component I listen for those events and change the $ref :D






              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                After good sleep I found answer:



                I made:



                window.Event = new class {
                constructor() {
                this.vue = new Vue();
                }

                fire(event, data = null) {
                this.vue.$emit(event, data);
                }

                listen(event, callback) {
                this.vue.$on(event, callback);
                }
                };

                const router = new VueRouter({routes: Routes, mode: 'history'});

                router.beforeEach((to, from, next) => {
                Event.fire('loader-start', 'start');
                next();
                });

                router.afterEach((to, from) => {
                setTimeout(function() {
                Event.fire('loader-done', 'done');
                }, 500);
                });


                And inside component I listen for those events and change the $ref :D






                share|improve this answer












                After good sleep I found answer:



                I made:



                window.Event = new class {
                constructor() {
                this.vue = new Vue();
                }

                fire(event, data = null) {
                this.vue.$emit(event, data);
                }

                listen(event, callback) {
                this.vue.$on(event, callback);
                }
                };

                const router = new VueRouter({routes: Routes, mode: 'history'});

                router.beforeEach((to, from, next) => {
                Event.fire('loader-start', 'start');
                next();
                });

                router.afterEach((to, from) => {
                setTimeout(function() {
                Event.fire('loader-done', 'done');
                }, 500);
                });


                And inside component I listen for those events and change the $ref :D







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 11 at 11:42









                Learner

                52512




                52512






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244391%2fbeforerouteupdate-or-leave-does-not-react-in-single-file-component%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Full-time equivalent

                    Bicuculline

                    さくらももこ