vue2的keep-alive的总结vue
keep-alive 是Vue的内置组件,能在组件切换过程当中将状态保留在内存中,防止重复渲染DOM。结合vue-router中使用,能够缓存某个view
的整个内容。
基本使用以下:git
<keep-alive> <component> <!-- 该组件将被缓存! --> </component> </keep-alive>
通常有这样的需求,当咱们第一次进入列表页须要请求一下数据,当我从列表页进入详情页,详情页不缓存也须要请求下数据,而后返回列表页
有两个状况:
1. 直接点击浏览器的后退返回按钮。
2. 点击导航栏中的 /list的连接返回。github
那么针对第一种状况下,咱们直接经过后退按钮时,返回到列表页(/list) 是不须要请求数据。
针对第二种状况下,咱们经过连接返回到列表页是须要请求数据。ajax
因此这边有三种状况:
1. 默认进来列表页须要请求数据。
2. 进入详情页后,经过浏览器默认后退按钮返回,是不须要ajax的请求的。
3. 进入详情页后,经过点击连接返回到列表页后,也是须要发ajax请求的。vue-router
配置以下:
1. 入口文件 app.vue 的配置以下:浏览器
<!-- 缓存全部的页面 --> <keep-alive> <router-view v-if="$route.meta.keep_alive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keep_alive"></router-view>
2. 在router中设置meta属性,设置 keepAlive: true 表示须要使用缓存,false的话表示不须要使用缓存。且添加滚动行为 scrollBehavior
router/index.js 的配置以下:缓存
import Vue from 'vue'; import Router from 'vue-router'; // import HelloWorld from '@/views/HelloWorld'; Vue.use(Router); const router = new Router({ mode: 'history', // 访问路径不带井号 须要使用 history模式,才能使用 scrollBehavior base: '/page/app', // 配置单页应用的基路径 routes: [ { path: '/', name: 'list', component: resolve => require(['@/views/list'], resolve), // 使用懒加载 meta: { keepAlive: true // true 表示须要使用缓存 } }, { path: '/list', name: 'list', component: resolve => require(['@/views/list'], resolve), // 使用懒加载 meta: { keepAlive: true // true 表示须要使用缓存 false表示不须要被缓存 } }, { path: '/detail', name: 'detail', component: resolve => require(['@/views/detail'], resolve) // 使用懒加载 } ], scrollBehavior (to, from, savedPosition) { // 保存到 meta 中,备用 to.meta.savedPosition = savedPosition; if (savedPosition) { return { x: 0, y: 0 }; } return {}; } }); export default router;
3. list.vue 代码以下:app
<template> <div class="hello"> <h1>vue</h1> <h2>{{msg}}</h2> <router-link to="/detail">跳转到detail页</router-link> </div> </template> <script> export default { name: 'helloworld', data () { return { msg: 'Welcome to Your Vue.js App' }; }, methods: { ajaxRequest() { const obj = { 'aa': 1 }; Promise.all([this.$store.dispatch('testUrl', obj)]).then((res) => { console.log(res); }); } }, beforeRouteEnter(to, from, next) { next(vm => { /* 若是 to.meta.savedPosition === undefined 说明是刷新页面或能够叫第一次进入页面 须要刷新数据 若是savedPosition === null, 那么说明是点击了导航连接; 此时须要刷新数据,获取新的列表内容。 不然的话 什么都不作,直接使用 keep-alive中的缓存 */ if (to.meta.savedPosition === undefined) { vm.ajaxRequest(); } if (to.meta.savedPosition === null) { vm.ajaxRequest(); } }) } }; </script>
4. detail.vue 代码以下:ui
<template> <div class="list"> <h1>{{msg}}</h1> <router-link to="/list">返回列表页</router-link> </div> </template> <script> export default { name: 'list', data () { return { msg: 'Welcome to Your Vue.js App' }; }, created() { this.ajaxRequest(); }, methods: { ajaxRequest() { const obj = { 'aa': 1 }; Promise.all([this.$store.dispatch('withdary', obj)]).then((res) => { console.log(res); }); } } }; </script>
二:使用router.meta 扩展this
假设如今有3个页面,需求以下:
1. 默认有A页面,A页面进来须要一个请求。
2. B页面跳转到A页面,A页面不须要从新请求。
3. C页面跳转到A页面,A页面须要从新请求。
实现方式以下:
在 A 路由里面设置 meta 属性:
{ path: '/a', name: 'A', component: resolve => require(['@/views/a'], resolve), meta: { keepAlive: true // true 表示须要使用缓存 } }
因此router/index下的全部代码变为以下:
import Vue from 'vue'; import Router from 'vue-router'; // import HelloWorld from '@/views/HelloWorld'; Vue.use(Router); const router = new Router({ mode: 'history', // 访问路径不带井号 须要使用 history模式,才能使用 scrollBehavior base: '/page/app', // 配置单页应用的基路径 routes: [ { path: '/', name: 'list', component: resolve => require(['@/views/list'], resolve), // 使用懒加载 meta: { keepAlive: true // true 表示须要使用缓存 } }, { path: '/list', name: 'list', component: resolve => require(['@/views/list'], resolve), // 使用懒加载 meta: { keepAlive: true // true 表示须要使用缓存 false表示不须要被缓存 } }, { path: '/detail', name: 'detail', component: resolve => require(['@/views/detail'], resolve) // 使用懒加载 }, { path: '/a', name: 'A', component: resolve => require(['@/views/a'], resolve), meta: { keepAlive: true // true 表示须要使用缓存 } }, { path: '/b', name: 'B', component: resolve => require(['@/views/b'], resolve) }, { path: '/c', name: 'C', component: resolve => require(['@/views/c'], resolve) } ], scrollBehavior (to, from, savedPosition) { // 保存到 meta 中,备用 to.meta.savedPosition = savedPosition; if (savedPosition) { return { x: 0, y: 0 }; } return {}; } }); export default router;
在 B 组件里面设置 beforeRouteLeave
beforeRouteLeave(to, from, next) { // 设置下一个路由meta to.meta.keepAlive = true; // 让A缓存,不请求数据 next(); // 跳转到A页面 }
B组件全部代码以下:
<template> <div class="list"> <h1>{{msg}}</h1> <router-link to="/a">返回a页面</router-link> </div> </template> <script> export default { name: 'list', data () { return { msg: 'Welcome to B Page' }; }, created() {}, methods: { }, beforeRouteLeave(to, from, next) { // 设置下一个路由meta to.meta.keepAlive = true; // 让A缓存,不请求数据 next(); // 跳转到A页面 } }; </script>
在 C 组件里面设置 beforeRouteLeave:
beforeRouteLeave(to, from, next) { // 设置下一个路由meta to.meta.keepAlive = false; // 让A不缓存,从新请求数据 console.log(to) next(); // 跳转到A页面 }
c组件全部代码以下:
<template> <div class="list"> <h1>{{msg}}</h1> <router-link to="/a">返回a页面</router-link> </div> </template> <script> export default { name: 'list', data () { return { msg: 'Welcome to B Page' }; }, created() {}, methods: { }, beforeRouteLeave(to, from, next) { // 设置下一个路由meta to.meta.keepAlive = false; // 让A不缓存,从新请求数据 console.log(to) next(); // 跳转到A页面 } }; </script>
a组件内的全部的代码以下:
<template> <div class="hello"> <h1>vue</h1> <h2>{{msg}}</h2> <router-link to="/b">跳转到b页面</router-link> <router-link to="/c">跳转到c页面</router-link> </div> </template> <script> export default { name: 'helloworld', data () { return { msg: 'Welcome to A Page' }; }, methods: { ajaxRequest() { const obj = { 'aa': 1 }; Promise.all([this.$store.dispatch('testUrl', obj)]).then((res) => {}); } }, beforeRouteEnter(to, from, next) { next(vm => { /* 若是 to.meta.savedPosition === undefined 说明是刷新页面或能够叫第一次进入页面 须要刷新数据 若是to.meta.keepAlive === false, 那么说明是须要请求的; 此时须要刷新数据,获取新的列表内容。 不然的话 什么都不作,直接使用 keep-alive中的缓存 */ if (to.meta.savedPosition === undefined) { vm.ajaxRequest(); } if (!to.meta.keepAlive) { vm.ajaxRequest(); } }) } }; </script>
注意 b组件到a组件不从新请求数据 (包括点击连接和浏览器后退按钮),c组件到a组件请求数据(包括点击连接和浏览器后退按钮).