【问题标题】:Keep alive view-router by key param通过关键参数保持活动视图路由器
【发布时间】:2018-12-09 13:08:29
【问题描述】:

如何分别使用不同的参数保持 vue-router 活着?

TL:DR

让我们考虑一个开发像 facebook 这样的网站的例子。每个用户都有一个个人资料页面。因为有很多用户,我们不想迭代所有用户并在加载时加载所有个人资料页面,如下所示

<template v-for="profile in profilePages">
   <profile-page :data="profile" v-show="this.route.params['id'] === channel.id"/>
</template>

常见的方法是:

router.js

{
  component: ProfileWrapper,
  path: '/profile',
  children: [
    {
      path: ':id',
      component: ProfilePage
    }
  ]
}

频道页

<keep-alive>
   <router-view :=key="$route.fullPath"></router-view>
</keep-alive>

但这就是问题所在。由于用户访问某人的页面并导航离开,我希望路由器将其保持在缓存中的某个地方,或者只是隐藏它。在我的特殊情况下,用户最多访问 2-3 个配置文件并在它们之间切换很多。而且切换操作很费时间,因为里面有很多DOM。

我可以使用 vue-routerkeep-alive 吗?

编辑

请查看sandbox。每次在页面之间切换 (#1,#2,#3,#4) Vue 从头开始​​创建新组件 ProfileInnerComponent(而不是像 v-show 那样从缓存中)。这通过检查红色 div 很明显,ProfileInnerComponentcreate 钩子被调用,它发出事件,App 将 div 添加到当前时间。

【问题讨论】:

  • 一个更好的例子,明白你想要什么?对不起,我不明白
  • @roliroli 请查看sandbox,底部有一个控制台选项卡,请打开它。在页面(#1、#2、#3、#4)之间打开切换。你会发现控制台出现Some component created again time ??消息,这意味着每次切换vue都会重新渲染页面

标签: vue.js vue-router


【解决方案1】:

为了使其工作,您需要在组件上使用唯一名称,然后您将使用 &lt;keep-alive&gt; 上的 include 属性。

<keep-alive include="Foo,Bar">
  ...
</keep-alive>

在您的情况下,使用动态组件而不是单个路由会更好。

<component :is="$route.params.id"></component>

keep-alive with Dynamic Components

keep-alive API reference

更新

根据查询参数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.
    }
  }
}

【讨论】:

  • 让我们将每个Channel 组件视为数据库实体,其中:id 是其标识。因此用户可以在运行时添加新频道。所有通道都具有相同的结构,我如何以及为什么为它们创建单独的组件?此外,我不知道它们的数量。
  • 在这种情况下,您只需要一个组件,比如Channel。要访问特定频道,您需要像 /channel/:id 这样的路由。然后可以使用beforeRouteEnter 导航守卫预取频道的内容。文档here contain examples
  • 这仍然不能解决在channels 之间导航时Vue 会重新渲染整个内容的问题,是吗?重新渲染不是指做 XHR 请求,我指的是重新创建 dom 结构。问题是组件Channel 很大,它的某些部分使用本机html 呈现(是的,我知道运行时模板编译,没有案例),并且从头开始重新创建它的时间成本很高。这就是我想要它懒惰的原因。
  • 如果你使用watch: { '$route' } 它应该重用组件。或者使用 beforeRouteUpdate 生命周期钩子,两者都不会重新创建整个组件。文档here explain further
  • 我真的不擅长解释我猜,Channel 的结构相同,但内容不同,channel#1 循环中可能包含 100 个元素,channel#2 中可能包含 1000 个元素循环,虽然结构是预定义的,但dom内容取决于远程API。如果我看route,只有channel 页面上的静态内容保持不变,而循环之类的内容会重新呈现。
【解决方案2】:

我通过添加以下代码更改了您的沙盒:

// in App.vue

<keep-alive>
   <router-view :key="$route.fullPath"></router-view>
</keep-alive>

//in Profile.vue

  <keep-alive>
    <profile-inner-component v-for="i in comps" :key="i" :data="i"/>
  </keep-alive>

【讨论】:

    【解决方案3】:

    我不确定我是否理解正确,但假设您有 2 页。

    Admins 和 Users,每个页面都有一个 counter,最初为 0。

    因此,当您在管理员页面并增加计数器时,您希望在导航到另一个页面并返回管理员页面时计数器与您离开时一样。

    我为此做了一个sandbox。另外请保持打开控制台查看组件被渲染了多少次。

    注意,在沙盒示例中,说明了如何实现这一点的逻辑。切勿在router-view 中使用keep-alive App.vue

    【讨论】:

    • 请查看我的sandbox。假设您正在开发像 facebook 这样的网站,所以每个用户都有他/她的页面。您不知道每个用户 ID,每个用户页面都有数千个节点(如 DIV)。每个用户都可以浏览其他用户页面,page 是一个 vue 组件。不像 userA 有 A.vue 而 userB 有 B.vue,所有页面都使用 Common.vue:id 参数。现在,当用户访问pageA,然后是pageB,然后是pageApageA 应该从缓存中渲染(或类似 v-show 的东西)。在我的沙箱中 Channel.vue 在访问时从头开始渲染
    • 是的,并且在我的回答中提供的这个沙箱中,它没有重新渲染。你可以检查一下
    • 您的沙箱有不同的页面,按名称缓存。我的沙箱是一个单页Channel.vue,可以加载不同的 ':id' 参数,这就是我试图解释的区别
    猜你喜欢
    • 2017-08-24
    • 2020-04-06
    • 1970-01-01
    • 2018-03-24
    • 2018-04-09
    • 2021-05-18
    • 1970-01-01
    • 2021-04-13
    • 2018-09-14
    相关资源
    最近更新 更多