vue2的keep-alive的总结

keep-alive 是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。结合vue-router中使用,可以缓存某个view
的整个内容。
基本使用如下:

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

一般有这样的需求,当我们第一次进入列表页需要请求一下数据,当我从列表页进入详情页,详情页不缓存也需要请求下数据,然后返回列表页
有两个情况:
1. 直接点击浏览器的后退返回按钮。
2. 点击导航栏中的 /list的链接返回。

那么针对第一种情况下,我们直接通过后退按钮时,返回到列表页(/list) 是不需要请求数据。
针对第二种情况下,我们通过链接返回到列表页是需要请求数据。

所以这边有三种情况:
1. 默认进来列表页需要请求数据。
2. 进入详情页后,通过浏览器默认后退按钮返回,是不需要ajax的请求的。
3. 进入详情页后,通过点击链接返回到列表页后,也是需要发ajax请求的。

配置如下:
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 代码如下:

<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 代码如下:

<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 扩展

假设现在有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组件请求数据(包括点击链接和浏览器后退按钮).

查看github上的代码

vue2的keep-alive的总结的更多相关文章

  1. vue2.0实践的一些细节

    最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...

  2. 用FSM一键制作逐帧动画雪碧图 Vue2 + webpack

    因为工作需要要将五六十张逐帧图拼成雪碧图,网上想找到一件制作工具半天没有找到,就自己用canvas写了一个. 写成之后就再没有什么机会使用了,因此希望有人使用的时候如果遇到bug了能及时反馈给我. 最 ...

  3. vue2.0构建淘票票webapp

    项目描述 之前一直用vue1.x写项目,最近为了过渡到vue2.0,特易用vue2.0栈仿写了淘票票页面,而且加入了express作为后台服务. 前端技术栈:vue2.0 + vue-router + ...

  4. Vuex2.0+Vue2.0构建备忘录应用实践

    一.介绍Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适合于构建中大型单页应用. ...

  5. 一步步构造自己的vue2.0+webpack环境

    前面vue2.0和webpack都已经有接触了些(vue.js入门,webpack入门之简单例子跑起来),现在开始学习如何构造自己的vue2.0+webpack环境. 1.首先新建一个目录vue-wk ...

  6. Vue2.0组件间数据传递

    Vue1.0组件间传递 使用$on()监听事件: 使用$emit()在它上面触发事件: 使用$dispatch()派发事件,事件沿着父链冒泡: 使用$broadcast()广播事件,事件向下传导给所有 ...

  7. 基于Vue2.0+Vue-router构建一个简单的单页应用

    爱编程爱分享,原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/6185492.html 一.介绍 vue.js 是 目前 最火的前端框架,vue.js ...

  8. vue2.0实战

    学了几周的vue2.0,终于有时间去做一个应用了. 为了全面联系相关知识,所以用到了vue-router,以及作者最新推荐的axios,组件库用的是饿了么的mint-ui2.0. 项目构建使用官方vu ...

  9. vue DatePicker vue2.0的日期插件

    一个用vue2.0写的日期控件,可以支持简单的年月日选择.地址:https://github.com/Stevenzwzhai/vue-datepicker. 首先是关于日期对象的使用,基本就是日期的 ...

  10. vue2/vuex2的那点坑

    说是坑,其实大部分是我们自己的过错! vuex官方demo在1.0可以运行,在2.0报错?此类问题,应该很常见吧? 还有顺溜的利用1.0搭建的webpack编译环境到了vue2.0突然失效了,报错了? ...

随机推荐

  1. poj 2566 Bound Found

    Bound Found Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4384   Accepted: 1377   Spe ...

  2. Matrix Again(最大费用最大流)

    Matrix Again Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Tota ...

  3. 暑假练习赛 003 B Chris and Road

    B - Chris and Road Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:262144K ...

  4. Tomcat请求头过大

    今天开发反应Tomcat的请求头过大 <Connector port="8280" protocol="HTTP/1.1" connectionTimeo ...

  5. 蓝桥杯-算法训练--ALGO-8 操作格子

    问题描述 有n个格子,从左到右放成一排,编号为1-n. 共有m次操作,有3种操作类型: 1.修改一个格子的权值, 2.求连续一段格子权值和, 3.求连续一段格子的最大值. 对于每个2.3操作输出你所求 ...

  6. Servlet的理解

    一.什么是Servlet? Servlet是用Java编写的web组件,实际上可以简单的理解为是用来处理请求的,为什么这么说,看了它的生命周期就知道了. 二.常见的Servlet容器 4容器顾名思义是 ...

  7. Adobe Html5 Extension开发初体验

    一.背景介绍       Adobe公司出品的多媒体处理软件产品线较多,涵盖了音视频编辑.图像处理.平面设计.影视后期等领域.为了扩展软件的功能,Adobe公司为开发者提供了两种方式来增加软件的功能: ...

  8. C#中简单的this与get的用法(string,decimal)

    代码 namespace First{publicpartialclass Form1 : Form{public Form1(){InitializeComponent();} privatevoi ...

  9. Gmail,QMail,163邮箱的 IMAP/SMTP/POP3 地址

    我们在客户端设置邮箱或者使用 PHPMailer 发送邮件的时候,我们都会去查找这些邮箱的 IMAP/SMTP/POP3 地址,这里就列出 Gmail, QMail, 163邮箱这三个常用邮箱的这些地 ...

  10. Redis使用说明详解

    原博主地址:http://www.cnblogs.com/wangyuyu/p/3786236.html Redis使用详细教程 一.Redis基础部分: 1.redis介绍与安装比mysql快10倍 ...