Keep alive view-router by key param

Multi tool use
Keep alive view-router by key param
How do I keep vue-router alive with different params separately?
TL:DR:
Let's consider an example when we're developing a website like facebook. Each user has a profile page. Because there are a lot of users we don't want to iterate all users and load all profile page on load like bellow
<template v-for="profile in profilePages">
<profile-page :data="profile" v-show="this.route.params['id'] === channel.id"/>
</template>
The common approach would be:
router.js:
{
component: ProfileWrapper,
path: '/profile',
children: [
{
path: ':id',
component: ProfilePage
}
]
}
ChannelsPage:
<keep-alive>
<router-view :=key="$route.fullPath"></router-view>
</keep-alive>
But here's the issue. Since user visits someone's page and navigates away, I want the router to keep it alive in cache somewhere, or just hide it. In my particular case, user visits 2-3 profile at most and switches a lot between them. And switching operation is time costly, because there are a lot of DOM in it.
Can I do it with vue-router and keep-alive?
EDIT:
Please check the sandbox. Each time you switch between pages (#1,#2,#3,#4) Vue
creates new components ProfileInnerComponent
from the scratch (not from the cache like v-show). That's noticeably by checking red div, the create
hook of ProfileInnerComponent
is called, which emits the event, and App
adds the div with current time.
Vue
ProfileInnerComponent
create
ProfileInnerComponent
App
@roliroli please check the sandbox, There's a console tab right at the bottom, please open it. While it's open switch between pages (#1,#2,#3,#4). You will find
Some component created again time ??
messages appear in console, which means vue rerenders page each time I switch it– deathangel908
Jun 30 at 23:12
Some component created again time ??
2 Answers
2
In order this to work you need unique names on your components, which you would then use the include
property on <keep-alive>
.
include
<keep-alive>
<keep-alive include="Foo,Bar">
...
</keep-alive>
In you case, you would be better served using dynamic components rather than a single route.
<component :is="$route.params.id"></component>
keep-alive with Dynamic Components
keep-alive API reference
update
Pre-fetching channel content based on the query param id:
// routes.js
routes = [
{
path: '/channel/:id',
name: 'show.channel',
props: true,
component: Channel
}
...
]
// Channel.vue
import axios from 'axios'
export default {
data () {
return {
content: ''
}
}
beforeRouteEnter(to,from,next) {
axios.get('/api/channel/' + to.params.id).then(response => {
next(vm => {
vm.content = reponse.data
})
})
},
watch: {
'$route' (to, from) {
// fetch new channel content when a query param is changed.
}
}
}
Let's consider each
Channel
component as database entity, where :id
is its identified. So a user can add new channel in runtime. All the channel have the same structure, how and why I create separate components for them? Furthermore, I don't know amount of them.– deathangel908
Jun 30 at 23:16
Channel
:id
In that case, you would only need one component, let's just say
Channel
. To access a specific channel you'd need a route like /channel/:id
. Then the channel's content could be pre-fetched using the beforeRouteEnter
navigation guard. The docs here contain examples– DigitalDrifter
Jun 30 at 23:22
Channel
/channel/:id
beforeRouteEnter
This still doesn't solve the issue that on navigating between
channels
Vue would re-render the whole thing all over again, does it? By re-rendering I don't mean doing XHR request, I mean recreating dom structure. The issue is that component Channel
is vast, some of its parts using native html rendering (yes, I'm aware of runtime template compile, there's no a case) and it's time-costly to re-create it from the scratch. That's why I want it lazy.– deathangel908
Jun 30 at 23:33
channels
Channel
If you use
watch: { '$route' }
it should reuse the component. Or use the beforeRouteUpdate
lifecycle hook, both of which will not recreate the entire component. Docs here explain further– DigitalDrifter
Jun 30 at 23:40
watch: { '$route' }
beforeRouteUpdate
I really bad at explaining I guess, the structure of
Channel
is the same, but the content is different, channel#1
may contain 100 elements in loop, channel#2
may contain 1000 elements in loop, while the structure is predefined, the dom content depends on remote API
. If I watch the route
, only the static things on the channel
page would remain the same, while things like loops would rerender.– deathangel908
Jul 1 at 0:01
Channel
channel#1
channel#2
API
route
channel
I am not sure if i understand correctly but lets suppose you have 2 pages.
Admins and Users and each page has an counter
which is initially 0.
counter
So you want when you are in Admins page and you increasing the counter,when navigating to another page and return back to Admins page the counter to be as you have left it.
I made a sandbox for this.Also please keep open the console to see how many times the components is rendered.
NOTE that in the sandbox example,is illustrated the logic how to achieve this.Never use keep-alive in router-view
in App.vue
.
router-view
App.vue
Please check my sandbox. Suppose you're developing website like facebook, so each user has his/her page. You don't know each user id, and each user page has thousand nodes (like DIVs). Each user can navigate through other user pages, and the
page
is a vue component. It's not like userA has A.vue
and userB has B.vue
, all pages use Common.vue
with :id
param. Now when user visits pageA
, then pageB
and then pageA
, pageA
should render from cache (or something like v-show). In my sandbox Channel.vue
renders from scratch upon visit– deathangel908
Jul 1 at 23:09
page
A.vue
B.vue
Common.vue
:id
pageA
pageB
pageA
pageA
Channel.vue
Yes, and in this sandbox provided in my answer,it is not rerendered.You can check it
– roli roli
Jul 2 at 7:31
Your sandbox have different pages, that are cached by name. My sandbox is a single page
Channel.vue
that can be loaded with different ':id' parameter, that's the difference I tried to explained– deathangel908
Jul 2 at 10:20
Channel.vue
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
A better example case, to understand what you want?I am sorry but i don't understand
– roli roli
Jun 30 at 20:39