vue-router 之 keep-alive

作者: 於風聽語 | 来源:发表于2017-04-06 11:14 被阅读19350次

本文基于 Vue2.0

keep-alive 简介

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
用法也很简单:

<keep-alive>
  <component>
    <!-- 该组件将被缓存! -->
  </component>
</keep-alive>

props

  • include - 字符串或正则表达,只有匹配的组件会被缓存
  • exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
// 组件 a
export default {
  name: 'a',
  data () {
    return {}
  }
}
<keep-alive include="a">
  <component>
    <!-- name 为 a 的组件将被缓存! -->
  </component>
</keep-alive>可以保留它的状态或避免重新渲染
<keep-alive exclude="a">
  <component>
    <!-- 除了 name 为 a 的组件都将被缓存! -->
  </component>
</keep-alive>可以保留它的状态或避免重新渲染

遇见 vue-router

西湖雨好大,借把伞躲躲雨...
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:

<keep-alive>
    <router-view>
        <!-- 所有路径匹配到的视图组件都会被缓存! -->
    </router-view>
</keep-alive>

然而产品汪总是要改需求,拦都拦不住...

问题

如果只想 router-view 里面某个组件被缓存,怎么办?

  • 使用 include/exclude
  • 增加 router.meta 属性

使用 include/exclude

// 组件 a
export default {
  name: 'a',
  data () {
    return {}
  }
}
<keep-alive include="a">
    <router-view>
        <!-- 只有路径匹配到的视图 a 组件会被缓存! -->
    </router-view>
</keep-alive>

exclude 例子类似。

缺点:需要知道组件的 name,项目复杂的时候不是很好的选择

增加 router.meta 属性

// routes 配置
export default [
  {
    path: '/',
    name: 'home',
    component: Home,
    meta: {
      keepAlive: true // 需要被缓存
    }
  }, {
    path: '/:id',
    name: 'edit',
    component: Edit,
    meta: {
      keepAlive: false // 不需要被缓存
    }
  }
]
<keep-alive>
    <router-view v-if="$route.meta.keepAlive">
        <!-- 这里是会被缓存的视图组件,比如 Home! -->
    </router-view>
</keep-alive>

<router-view v-if="!$route.meta.keepAlive">
    <!-- 这里是不被缓存的视图组件,比如 Edit! -->
</router-view>

优点:不需要例举出需要被缓存组件名称

【加盐】使用 router.meta 拓展

假设这里有 3 个路由: A、B、C。

  • 需求:

    • 默认显示 A
    • B 跳到 A,A 不刷新
    • C 跳到 A,A 刷新
  • 实现方式

    • 在 A 路由里面设置 meta 属性:
{
        path: '/',
        name: 'A',
        component: A,
        meta: {
            keepAlive: true // 需要被缓存
        }
}
  • 在 B 组件里面设置 beforeRouteLeave
export default {
        data() {
            return {};
        },
        methods: {},
        beforeRouteLeave(to, from, next) {
             // 设置下一个路由的 meta
            to.meta.keepAlive = true;  // 让 A 缓存,即不刷新
            next();
        }
};
  • 在 C 组件里面设置 beforeRouteLeave
export default {
        data() {
            return {};
        },
        methods: {},
        beforeRouteLeave(to, from, next) {
            // 设置下一个路由的 meta
            to.meta.keepAlive = false; // 让 A 不缓存,即刷新
            next();
        }
};

这样便能实现 B 回到 A,A 不刷新;而 C 回到 A 则刷新。

实现前进刷新,后退不刷新

感谢 iceuncle 分享的 《vue实现前进刷新,后退不刷新》

总结

路由大法不错,不需要关心哪个页面跳转过来的,只要 router.go(-1) 就能回去,不需要额外参数。

然而在非单页应用的时候,keep-alive 并不能有效的缓存了= =

参考

—— 2017/04/06 By Live, haze currently.

相关文章

  • keep-alive实现原理

    一、前言 本文介绍的内容包括: keep-alive用法:动态组件&vue-router keep-alive源码...

  • vue-router 之 keep-alive

    keep-alive 简介 keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重...

  • vue-router 之 keep-alive

    本文基于 Vue2.0 keep-alive 简介 keep-alive 是 Vue 内置的一个组件,可以使被包含...

  • vue-router 之 keep-alive

    keep-alive 简介 keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重...

  • 浅谈 vue项目优化

    1.路由懒加载 使用vue-router的方法 2.图片懒加载 组件缓存 使用vue的,详...

  • keepalive配合标签页进行注册和销毁

    技术栈:vue,vue-router 是什么 keep-alive是vue中提供缓存不活动组件的标签,可以支持一些...

  • Vue-router中keep-alive的理解

    Vue-router的API文档中对于keep-alive的介绍并不多,所以对于初学者来说,可能并不太理解什...

  • vue-router 页面缓存之 keep-alive

    项目中会有这样的需求,有的页面需要缓存(例如列表页),有的页面不需要缓存(例如详情页),这时候就需要 keep-a...

  • @面试题全部

    面试题第一天 1:vuex工作流程2:vue-router导航守卫(钩子函数)3:详述keep-alive组件 面...

  • Vue-router中keep-alive的理解

    Vue-router的API文档中对于keep-alive的介绍并不多,所以对于初学者来说,可能并不太理解什么是k...

网友评论

  • ae01ce2c3101:先是由A进入B,这两个的keepAlive都是true,从A进入B我将B的keepAlive设置为false,但是从B后退到A,,A页面就没使用缓存,请问这是为什么?
  • 479577f34797:博主的方案貌似第一次进去的时候keep-alive被改为了false 所以第一次进入的时候页面无法缓存 但是之后的操作就可以了(主页->列表页->详情页,需要主页进入列表页清除缓存,详情页跳到列表页保存缓存,但是目前的情况是第一次从主页进入列表页再进入详情页后返回列表页列表页并没有进行界面缓存,但之后再进行该操作又可以了,刷新界面又不行)亲测,是主页进入列表页将keep-alive改成了false造成的后果,有解决方案吗?我试了好多种都没有用,求指教
  • 空想之屿:我这里有个需求,A页面是首页,B页面是个人页,从A页面进入B页面后,B页面点击返回A页面缓存A页面,而B页面右上角的更多功能里的首页按钮点击进入A页面则刷新A页面,这个需求有思路吗
    a005769539d5:@屿_83e2 写一个全局变量needrefresh,当从右上角回首页的时候,赋值true,然后在activated生命周期里判断这个全局变量,如果是true,就强制刷新页面
    於風聽語:https://jsfiddle.net/Roam/s2erq3b6/61/
    A 页面 Count ++ ,再到 B,这样对比缓存效果
  • ZavierTang:您好!为什么我使用了
    <keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
    然后设置route中的meta.keepAlive = false后页面不见了,经过多次尝试发现第二个<router-view>没有渲染,可以解答一下吗?谢谢
    9e929d4e5b5a:那就是第二个路由的路径不对呗:kissing_heart:
  • 0c2841149040:楼主 为啥我项目跑起来还meta的keepAlive属性就是undefined
  • 小小野心:感觉最后一个例子 A-B-C三个路由跳转有问题
    如果你从C界面跳转到A界面之后做一些操作
    在跳转到B界面,再从B界面返回A界面,此时keepAlive = true
    但是A界面并不会缓存
    或者缓存的是之前B界面到A界面缓存的数据
    动态的调整一个界面的缓存还是用include/exclude
    苏打丶观:同遇到这个问题。。。有何解决方案么?
  • ee768aba7de8:你好 楼主 我想问一下 为什么我设置了 keepAlive: true,之后 导航菜单的切换出了问题呢?
    ee768aba7de8:就是切换需要缓存那个菜单 跳转错误
  • 30e7785486c3:keepAlive的思路,是不是抄的我的
    30e7785486c3:@RoamIn 还真可能是,以前发过这个思路的博文
    於風聽語:忘了哪里看到的了
  • 於風聽語:@千寻她妹 每次进入离开 BC,进入 A 之前,即 beforeRouteLeave,需要更新 to.meta.keepAlive,因为离开 BC 会重写 A 的 keepAlive
    c18277028b7e:@RoamIn 嗯嗯 是的 我直接用sessionStorage保存了数据 keepAlive实现不了需求~
    於風聽語:@千寻她妹 这样会有问题,不能及时生效好像,我试过三级,出问题了
    c18277028b7e:嗯嗯 是的 因为其他页面也能进入A所以又在router.beforeEach中设置了if(from.path === '/B' && (to.path === '/A')) {
    to.meta.keepAlive = true
    }else {
    to.meta.keepAlive = false
    }
    就会出现首次从B返回A刷新 之后不再刷新的问题 但是console中第一次返回的时候也是to.meta.keepAlive = true 按道理不应该刷新才对 ?!
  • c18277028b7e:感谢分享 但是遇到一个问题就是从B-->A第一次刷新(但是keepAlive=true) 之后才不刷新 不解啊???
  • c50ad0d699ba:router里面,引入后的名字好像只对router的跳转识别,有效。
    component的name是可以被keep-alive读取的。
    所以,组件有名字还是非常必要的。
    如果keep-alive本身被丢掉了,那么,keep-alive保存的东西也就丢掉了。
    文章总结的几个办法,目测也是现阶段的唯二办法。
    於風聽語:@Tianfanfan 超过两层后,后一种就有问题了,还没思路...
  • 5edea3b599ac:大佬你这种方法貌似对a->b->c 前进刷新,c->b->a 后退不刷新。这种两个以上的路由不生效。也可能是我不得要领,望大佬指点两个以上路由前进刷新,后退不刷新的方法。
    SunnySky_:有什么方案吗?
    5edea3b599ac:@RoamIn 好的,期待大佬的新作
    於風聽語:我抽空整理一下
  • 3d576db79a59:为什么我的第一次进入c页面的时候不会被保存,而当再次进入c页面的时候才会起作用
    3910db1a05b8:@微光牧之 一样的问题 解决了没?
    cbde575fe02d:我也是这样,解决了吗
  • 不冷的豆豆:不错的,真好用到了我的项目中,谢谢
  • Zvit:感谢分享,解决了我的大问题!
  • d4c597eb0798:根组件:
    <keep-alive include="list">
    <router-view>
    </router-view>
    </keep-alive>

    路由页面:
    export default {
    name: 'list',
    data() {
    return {}
    }
    }

    没有起作用
    於風聽語:@一乐 我理解是 include 所直接包含的子组件,子组件里面的不会去查找的,https://github.com/vuejs/vue/blob/master/src/core/components/keep-alive.js
    d4c597eb0798:@RoamIn 那要缓存路由试图,还是添加meta那个好用。所以include只能缓存router-view中的组件是吗,router-view本身也是组件吧
    於風聽語:@一乐 使用 include,则 keep-alive 里面放的是组件[component],而不是路由[router-view]
  • 76bcd79b1601:好文,我最近也遇到这个问题,头疼死了!
    <keep-alive>
    <router-view>
    </router-view>
    </keep-alive>
    我只需要缓存其中一个页面,我使用了include属性但是不起作用·····
    於風聽語:@一乐 可能你写法有问题,可以发来看看,include 我试过的。
    d4c597eb0798:@RoamIn 我页面组件设置了name,include也没起作用,还是用用meta那个方法
    於風聽語:这个页面组件需要设置 name="a",如果你 include="a"

本文标题:vue-router 之 keep-alive

本文链接:https://www.haomeiwen.com/subject/ndifattx.html