I am using Vue.js 2.5.x and Nuxt 1.4. I believe this is a question related to vue-router.
I have the same component on two different Nuxt pages that I want to preserve in the layout (not just in memory) when navigating between the pages.
To put this in terms of lifecycle events, some components are added and removed from a layout and trigger a whole lifecycle of being created, mounted then unmounted, destroyed. I understand how keep-alive works to avoid the created/destroyed overhead of that process for components we expect to be re-mounted in the layout, and that isn't the question here.
In contrast, simple components seem to not be unmounted at all when a route changes, as though Vue somehow understands that these components will appear the same in two different layouts so not only does it not destroy/create them... it leaves them in the layout and doesn't even unmount them.
I am trying to get a better understanding of the conditions that allow a current page's components to remain mounted when navigating between routes. Many of the discussions I’ve found are of the nature of “Why isn’t my component refreshing?” when a route change happens, but I actually have the opposite problem: I want to preserve a component and its state, but the component is getting destroyed. I have played with setting 'key' explicitly to a specific shared value (the opposite advice usually given to insure components DO unmount) but there seems to be something deeper than this.
Again, for clarity, I'm not referring to "keep-alive" trying to hang onto components in memory that are temporarily removed from a layout. What I am observing and trying to understand here seems to be a different behavior, where some part of Vue recognizes components as being identical between two layouts and it optimizes away the destroy and (re)create of such components. This is a huge optimization, but one whose behavior doesn't seem to be discussed or documented anywhere I can find.
I have a Nuxt layout that is conceptually like this…
default.vue:
<template>
<div>
<my-marvelous-header-component />
<nuxt/>
<my-also-marvelous-footer-component />
</div>
</template>
…and I have a couple of Nuxt pages that look like this…
page-a.vue:
<template>
<section id=mainContent>
<wonderful-component id="wonder1" :key=321 />
<complex-component-with-children :key=123 />
</section>
</template>
page-b.vue:
<template>
<section id=mainContent>
<wonderful-component id="wonder1" :key=321 />
<complex-component-with-children :key=123 />
</section>
</template>
You’ll note that both pages have exactly the same components, and I’ve tried to identify them uniquely with key properties in an effort to communicate to Vue that these are the same creatures at render time.
When I navigate between these pages with this.$router.push(), my header and footer components survive the route navigation unmolested (I verified this by putting some console output in the lifecycle hooks), however both wonderful and complex components are destroyed and then recreated.
Both of the components I’m trying to recycle have a number of dynamically created child components inside of them, so the state of the vdom is going to be considerably different from the raw starting conditions of the initial page. Components like wonderful or complex don’t have any properties or any other data passed from the template… They are exactly as shown in the layout above. I’ve experimented with giving them a unique ID or key value that is shared across the templates (as well as nothing at all), but no matter what I have tried, the router push causes these components to destroy and re-render.
Trivial components like my header and footer recycle fine, I just want to make my more complex components behave likewise.
So my question centrally is, what allows or prevents recycling of components? What is examined to determine if a component can be recycled? Is there a way to signal that a component should be preserved/recycled between route changes? If not, what do I have to keep outside of the component to make it appear as a candidate for sticking around across transitions?
I had thought that the “key” property was the magic here, but that doesn’t seem to work and unfortunately browsing the Vue.js source for this word reveals that it is used quite extensively to name parameters and local variables… I believe there’s a function within Vue called “patch()” that deals with updating at least the vdom consistently with old and new components, but frankly the logic in there exceeds my present Vue knowledge. If someone with some better knowledge of the Vue internals had insights on what parts of the code might help clarify my thinking, I'd be keen to dive through this again.
I feel like I’ve been chasing my tail on this for several days. Any thoughts or insights are much appreciated.