Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Vue Router without remounting components?

Tags:

vue.js

I have a page that inherits an activeTab routing param from the URL path. So on my page, I can navigate to /home/ and load in the home tab, or at /somethingElse I can load in a different tab within my page template's tab viewport.

To update the tab, I'm using:

updateTab(tab) {
  this.activeTab = tab
  this.$router.push(tab)
}

When I do this, I get a flicker across the screen, and my mounted() functions are re-executed across every component, triggering an animation that should only be triggered on the application's first entry point.

This comes closer to the desired behavior, where the tab changes and I don't get a flicker or remounting of the components:

updateTab(tab) {
  this.activeTab = tab
  history.pushState({}, '', tab)
}

However, pushing the activeTab directly into the history seems to prevent the Back button from correctly restoring the previous state.

How can I update the path at the Vue Router without remounting all of my components?

like image 442
iRyanBell Avatar asked Mar 04 '18 20:03

iRyanBell


2 Answers

When router's path changes, components will mount again,if you want to mount component only one time, you can try the Vue's build-in component keep-alive, it will only trigger its activated hook and deactivated hook.And you can do something in these two hooks.

The html:

<div id="app">
      <router-link to="/link-one">link-one</router-link>
      <router-link to="/link-two">link-two</router-link>
       <keep-alive>
         <router-view>

         </router-view>
       </keep-alive>
 </div>

The javascript:

Vue.use(VueRouter);
        function createLink(path) {
            let routePath = '/' + path;
            return {
                path: routePath,
                component: {
                    name: path,
                    template: '<span>{{path}} mountedTimes:{{mountedTimes}}, activatedTimes: {{activatedTimes}}</span>',
                    data() {
                        return {
                            mountedTimes: 0,
                            activatedTimes: 0,
                            path: routePath
                        }
                    },
                    mounted() {
                      console.log('mounted')
                        this.mountedTimes++;
                    },
                    activated() {
                        this.activatedTimes++;
                    }
                }
            }
        }
        const routes = [createLink('link-one'), createLink('link-two')];
        const router = new VueRouter({
            routes
        })
        const app = new Vue({
            el: "#app",
            router
        })

CodePen

like image 124
wang Avatar answered Nov 15 '22 05:11

wang


This is not the expected behaviour. Components that do not change should not re-execute the mounted hook.

I would search for the problem someplace in the top of the vue component hierarchy, because it sounds like some other piece of code might force the re-rendering of the hierarchy.

like image 38
Joachim Bøggild Avatar answered Nov 15 '22 04:11

Joachim Bøggild