keep-alive理解

news/2024/11/19 19:29:45/

keep-alive理解

  • 理解
    • 定义:
    • 作用
    • 原理
  • 使用
    • 参数
      • *那么在实际开发中我们可以饥饿和路由守卫来实现需要缓存组件的缓存*

理解

定义:

是一个内置组件,当他包裹动态组件时,会缓存不活动的组件实例,而不是销毁他们
keep-alive是一个抽象组件,他不会渲染成一个dom元素,也不会出现在父组件链中

作用

如果组件是一个缓存状态,那么防止重复渲染dom,减少加载时间及性能消耗,提高用户体验性

原理

在 created 函数调用时将需要缓存的 VNode 【虚拟dom】节点保存在 this.cache 中/在 render(页面渲染) 时,如果 VNode 的 name 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode 实例进行渲染

使用

参数

参数名描述
include字符串或正则表达式只有名称匹配的组件会被缓存
exclude字符串或正则表达式任何名称匹配的组件都不会被缓存
max数字最多可以缓存多少组件实例

注意:include/exclude值是组件中的name名称,不是路由组件名称name命名

// router.js
{path: '/home',name: 'home',component: () => import('../views/home.vue')
},
{ path: '/about',name: 'about',component: () => import('../views/about.vue')
},
//首先声明只有两个页面分别是:home页面和about页面
// App.vue//所有组件都要缓存【情况一】
<keep-alive><router-view/>
</keep-alive>//如果只缓存about内容【情况二】
<keep-alive include="about"><router-view/>
</keep-alive>//如果不缓存about内容【情况三】
<keep-alive exclude="about"><router-view/>
</keep-alive>----------------------------------------------------------------------------------------------------------------
补充: include/exclude 值的多种形式。// 1. 将缓存 name 为 test 的组件(基本)
<keep-alive include='about'><router-view/>
</keep-alive>// 2. 将缓存 name 为 a 或者 b 的组件,结合动态组件使用
<keep-alive include='a,b'><router-view/>
</keep-alive>// 3. 使用正则表达式,需使用 v-bind
<keep-alive :include='/a|b/'><router-view/>
</keep-alive>	// 4.动态判断
<keep-alive :include='includedComponents'><router-view/>
</keep-alive>// 5. 将不缓存 name 为 test 的组件
<keep-alive exclude='home'><router-view/>
</keep-alive>// 6. 和 `<transition>` 一起使用
<transition><keep-alive><router-view/></keep-alive>
</transition>// 7. 数组 (使用 `v-bind`)
<keep-alive :include="['a', 'b']"><component :is="view"></component>
</keep-alive>
// 关于页about.vue
<template><div class="about"><h2>关于页</h2><p @click="pClick">这是一个p标签</p></div>
</template>
<script>
export default{name: 'AboutView',components: {},methods: {pClick(e) {console.log(e.target.style.color = 'red');console.log('p标签被点击了')}},created() {console.log('AboutView created')},destroyed() {console.log('AboutView destroyed')},
}
</script>
//首页home.vue
<template><div class="home"><h2>首页</h2></div>
</template><script>export default {name: 'HomeView',components: {},created() {console.log('HomeView created')},destroyed() {console.log('HomeView destroyed')},
}
</script>

那么此时如果是情况一那就是缓存了全部组件
如果是情况二,就只能看到about组件内的p标签内的内容被缓存啦,也就是说在进行home和about内容进行切换的时候,缓存about
如果是情况三那么就是缓存的home组件

此外,还有一种方法进行缓存
使用路由中的meta属性来进行控制,是否需要缓存

将about路由中的meta添加KeepAlive属性为true,表示当前路由要进行缓存

// router.js
{path: '/home',name: 'home',component: () => import('../views/home.vue')
},
{ path: '/about',name: 'about',meta:{keepAlive:true},component: () => import('../views/about.vue')
},

keep-alive 代码可以结合 v-if 进行包裹,如果 meta 中的 keepAlive 为 true 进行缓存,否侧不进行缓存

<keep-alive><router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />

那么在实际开发中我们可以饥饿和路由守卫来实现需要缓存组件的缓存

export default {beforeRouteLeave(to, from, next) {to.meta.keepAlive = true;next();}
}
</script>

那么使用路由缓存的时候势必会使用到生命周期钩子,那么下面来介绍一下和他相关的生命周期钩子函数

名称描述
actived在keep-alive组件激活时调用,该钩子函数在服务器端渲染期间不 被调用
deactived在keep-alive组件停用时调用,该钩子函数在服务器端渲染期间不 被调用

解释
使用会将数据保留在内存中,如果在每次进入页面的时候获取最新的数据,需要在actived阶段获取数据,承担原来created钩子中获取数据的任务
被包含在中创建的组件,会多出两个生命周期钩子:activated和deactivated

activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用
deactivated:在组件被停用时调用

注意:
只有组件被 keep-alive 包裹时,这两个生命周期才会被调用,如果作为正常组件使用,是不会被调用,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子依然不会被调用!另外在服务端渲染时此钩子也不会被调用的

什么时候获取数据?

当引入keep-alive的时候,页面第一次进入,钩子的触发顺序:
created==>mounted==》activated,
退出时触发deactivated
当再次进入时候,之触发activated

我们知道 keep-alive 之后页面模板第一次初始化解析变成 HTML 片段后,再次进入就不在重新解析而是读取内存中的数据。
只有当数据变化时,才使用 VirtualDOM 进行 diff 更新。所以,页面进入的数据获取应该在 activated 中也放一份。
数据下载完毕手动操作 DOM 的部分也应该在activated中执行才会生效。

所以,应该 activated 中留一份数据获取的代码,或者不要 created 部分,直接将 created 中的代码转移到 activated 中

实际应用:
如果未使用keep-alive组件,则在页面回退时会诚信渲染页面,触发created钩子,使用体验性不好

主要的使用场景就有:菜单存在多级关系【首页–》列表页–》详情页】

从首页跳转列表页面时,列表页面组件重新渲染;
当从详情页面返回列表页面时,列表组件缓存,不会重新请求数据

// app.vue
<template><div id="app"><keep-alive :include="keepAliveInclude"><router-view/></keep-alive></div>
</template><script>
import { mapGetters } from 'vuex'
export default {name:'home',computed:{...mapGetters(['keepAliveInclude',])},
}
</script>

store 中对 keepAliveInclude 的状态更新保存

// store.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {// keepAlive缓存组件keepAliveInclude:[],},getters:{keepAliveInclude: state => state.keepAliveInclude,},mutations: {SET_KEEPALIVEINCLUDE:(state, keepAliveInclude) => {state.keepAliveInclude = keepAliveInclude;}},actions: {setKeepAliveInclude({ commit }, keepAliveInclude){commit("SET_KEEPALIVEINCLUDE", keepAliveInclude)},},
})

需要进行缓存的页面 list.vue

<template><div><button @click="goHome">首页</button><button @click="goDetail">详情</button>列表: <input type="text" v-model="inputVal"></div>
</template><script>
export default {name:'list',data(){return {inputVal:'',}},methods:{goDetail(){this.$router.push('./detail')},goHome(){this.$router.push('./home')}},beforeRouteLeave (to, from, next) {if(to.name == 'detail'){this.$store.dispatch('setKeepAliveInclude',['list'])}else{this.$store.dispatch('setKeepAliveInclude',[])}// next();setTimeout(() => { next(); }, 10); // next()需用定时器包裹,否则多次切换无法缓存}
}
</script>

http://www.ppmy.cn/news/103617.html

相关文章

CH341的I2C接口编程说明

CH341的I2C接口特性&#xff1a; 1、支持I2C速度20K/100K/400K/750K&#xff1b; 2、默认不支持设备的ACK应答监测&#xff0c;即忽略ACK状态&#xff1b;强制支持需修改软件&#xff1b; 引脚序号功能说明24SCL23SDA Windows系统SPI通讯接口函数 HANDLE WINAPI CH341OpenD…

「实在RPA·运营商数字员工」为数智化升级打call

提起运营商&#xff0c;人们定不陌生&#xff0c;日常生活中与他人的联络互动以及各种信息平台的登录都离不开运营商的身影。除了提供了基础的通信服务之外&#xff0c;运营商还向用户提供了各种数字化产品和服务&#xff0c;例如云计算、大数据、物联网等&#xff0c;为用户提…

【数据结构】二叉树——链式结构的实现(代码演示)

目录 1 二叉树的链式结构 2 二叉树的创建 3 二叉树的遍历 3.1 前序遍历 3.1.1运行结果&#xff1a; 3.1.2代码演示图: 3.1.3 演示分析&#xff1a; 3.2 中序遍历 3.3 后序遍历 3.4 层序遍历 4 判断是否是完全二叉树 5 二叉树节点的个数 5.1 总个数 5.2 叶子节点…

​​​​Linux Shell 实现一键部署Oracle21 rpm包方式

oracle前言 Oracle开发的关系数据库产品因性能卓越而闻名&#xff0c;Oracle数据库产品为财富排行榜上的前1000家公司所采用&#xff0c;许多大型网站也选用了Oracle系统&#xff0c;是世界最好的数据库产品。此外&#xff0c;Oracle公司还开发其他应用程序和软件。同时&#…

深度学习笔记之循环神经网络(八)LSTM的轻量级变体——门控循环单元(GRU)

深度学习笔记之LSTM轻量级变体——门控循环单元[GRU] 引言回顾&#xff1a; LSTM \text{LSTM} LSTM的前馈计算过程 LSTM \text{LSTM} LSTM的问题 GRU \text{GRU} GRU的前馈计算过程 GRU \text{GRU} GRU的优势 引言 上一节介绍了从反向传播过程的角度认识 LSTM \text{LSTM} LST…

将文件base64解码后输出

Map taxPdf alService.getFile();//得到文件 String filestr String.valueOf(taxPdf.get("data")); if (taxPdf ! null) {BASE64Decoder decoder new BASE64Decoder();byte[] fileBytes decoder.decodeBuffer(filestr);HttpServletResponse response getRespons…

30分钟开发微信小程序并部署

30分钟开发微信小程序并部署 首先&#xff0c;今天我们会使用到腾讯为我们提供的云平台来协助我们小程序的开发和部署。 环境准备&#xff1a; 微信开发者账号&#xff08;自己在微信公众号平台注册一个账号&#xff09;&#xff1a;https://mp.weixin.qq.com/&#xff0c;同时…

[GUET-CTF2019]number_game[数独]

目录 题目 学到的知识点&#xff1a; 题目 在buu上看到了一道数独题&#xff0c;没见过&#xff0c;记录一下 下载附件&#xff0c;查壳&#xff0c;无壳&#xff0c;在IDA中打开&#xff0c;直接找到主函数 unsigned __int64 __fastcall main(int a1, char **a2, char **a3…