记一次keep-alive没有生效的排查

410 阅读2分钟

先贴问题代码

<keep-alive :include="[需要缓存的组件name]">
    <div class="main-content-wrapper">
        <router-view :key="path"/>
    </div>
</keep-alive>

乍一看,好像没啥问题呀,页面也能正确渲染,在所有的主显示界面上增加一个全局的样式

但测试过程中,问题就暴露出来了,每次切换页面都会重新请求

页面功能没啥问题,但就是缓存无效了,这不工作量就来了吗

由于这块不是我开发的,所以一开始,咱也不知道是啥问题呀

首先肯定查一下官方文档,没看出啥问题来

初步怀疑是不是include中的数据由问题呢?

但根据文档和路由参数,仔细比对,甚至写死固定值也解决不了

这么看来就不是配置问题了

接下来往哪个方向排查呢?

有问题就google,唉,好巧不巧,我发现网上写的那些,keep-alive下清一色的component

我这脾气就上来了,都是html,为啥我的就不行呢?

既然如此就先随便尝试一下呗,先把div干掉

这就一下子搞定了?有点懵

好奇心害死猫,我还真想知道为啥

于是就去搂搂源码了,别说,还真找到原因了

// vue.js 源码
  var KeepAlive = {
    name: 'keep-alive',
    // ...
    render: function render () {
      // 拿到默认的插槽内容
      var slot = this.$slots.default;
      // 拿到第一个直系子组件,必须是组件,因为只有组件才有name属性
      var vnode = getFirstComponentChild(slot);
      // ...
    }
  }

  // 查找并返回第一个直系"组件"
  function getFirstComponentChild (children) {
    if (Array.isArray(children)) {
      for (var i = 0; i < children.length; i++) {
        var c = children[i];
        if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
          return c
        }
      }
    }

省略其它无关的代码,在render函数中有一段代码就是专门获取keep-alive下第一个直系组件

记住,必须是直系组件,所以上述代码包裹div是不行的

最终的改动代码,将div放到keep-alive外即可

<div class="main-content-wrapper">
    <keep-alive :include="[需要缓存的组件name]">
        <router-view :key="path"/>
    </keep-alive>
</div>