vue keep-alive动态缓存问题

需求是这样的:列表页进入详情页,列表页需要缓存,但从列表页进入首页(或其他页面),列表页不缓存。

网上解决方案有很多,可惜我智商不够,没成功,后来摸索出了一个解决方法。

首先,看一下keep-alive的源码:

// 只看下面一段
mounted () {
  this.$watch('include', val => {
    pruneCache(this, name => matches(val, name))
  })
  this.$watch('exclude', val => {
    pruneCache(this, name => !matches(val, name))
  })
},

keep-alive监听了includeexclude。这里我只用到了include,做法是列表页一直缓存,在从列表页进入首页的时候,设置列表页不缓存,再调用this.$nextTick将列表页设置为缓存,防止下一次进入列表页的时候,列表页不在include中而没有缓存。有点绕,简单来说就是在进入首页的时候清一下列表页的缓存(重置)。代码如下:

// router.js
{
  path: '/latest',
  name: 'Latest',
  component: () => import('@/views/latest'),
  meta: {
    keep: true // 是否缓存组件
  }
}
<template>
  <div id="app">
    <Header></Header>
    <div class="content-container" :class="$route.meta.scroller ? 'no-padding' : ''">
      <keep-alive :include="cacheViews" ref="keepAlive">
        <router-view :key="$route.fullPath"></router-view>
      </keep-alive>
    </div>
  </div>
</template>

<script>
import Header from '@/components/Header'
export default {
  name: 'App',
  components: {
    Header
  },
  computed: {
    // 需要缓存的页面数组放到了 vuex 中
    cacheViews() {
      return this.$store.state.app.cacheViews
    }
  },
  watch: {
    $route: {
      handler(to, from) {
        this.changeKeep(to, from)
      }
    }
  },
  methods: {
    // 改变路由缓存字段
    changeKeep(to, from) {
      if (to.name === 'BookDetail') {
        from.meta.keep = true
      } else {
        from.meta.keep = false
        this.$nextTick(() => {
          from.meta.keep = true
          this.setCacheViews(to, from)
        })
      }
      this.setCacheViews(to, from)
    },
    // 设置缓存页面
    setCacheViews(to, from) {
      let routes = this.$router.options.routes
      routes = routes.filter(route => route.meta && route.meta.keep).map(route => route.name)
      this.$store.commit('app/SET_DATA', {
        cacheViews: routes
      })
      console.log(routes)
    },
  }
}
</script>

这样基本算是解决了keep-alive缓存的问题。


题外话:webApp的开发体验能不能更好一点呢?比如路由页面缓存、前进、后退等问题总是让人头疼。刚刚好像看到一个vue-page-stack插件,以后有空可以试一下。