Vue2 - keep-alive 作用和原理

目录

  • 1,介绍和作用
  • 2,原理
  • 3,使用场景
    • 3.1,效果展示
    • 3.2,实现思路

1,介绍和作用

<!-- 非活跃的组件将会被缓存! -->
<keep-alive><component :is="activeComponent" />
</keep-alive>

1,是一个内部组件,用于缓存组件实例。在组件切换时,不用重新创建而是使用缓存中的组件实例。

  • 可以避免创建组件的开销。
  • 可以保留组件状态

2,有3个属性:

  • includeexclude 属性,可以控制哪些组件进入缓存。
  • max 属性可以设置最大缓存数,当缓存的实例超过该数时,vue会移除最久没有使用的组件缓存。
<!-- 以英文逗号分隔的字符串 -->
<keep-alive include="Comp1,Comp2"><component :is="view" />
</keep-alive>
<!-- 数组 -->
<keep-alive :include="['Comp1', 'Comp2']"><component :is="view" />
</keep-alive>

3,受 keep-alive 影响,内部所有嵌套的组件都有2个生命周期函数。activateddeactivated。第1次 activated 是在 mounted 之后。

4,当嵌套组件是 <router-view> 时,缓存的是路由对应的组件。

因为 <router-view> 是函数式组件,只有一个目的,生成虚拟DOM。它没有状态,不生成实例。有穿透的效果。

<keep-alive><router-view></router-view>
</keep-alive>

2,原理

源码

keep-alive 在内部维护了一个缓存对象和 keys 数组:

// keep-alive 组件的生命周期函数
created () {this.cache = Object.create(null)this.keys = []
}
  • keys 数组记录当前缓存组件的 key,如果组件没有指定,则会自动为组件生成唯一的 key

  • cache 对象以 key 为键,vnode 为值,来缓存组件对应的虚拟 DOM。

keep-alive 组件的 render 函数中,大致逻辑:

判断当前渲染的 vnode 是否有对应的缓存,有则从缓存中读取对应组件实例,没有则将其缓存。当缓存数量 > max 时,会移除掉 keys 数组的第1个元素。

// 更新逻辑其实在 update 函数中,这里结合在一起容易理解。
render(){const slot = this.$slots.default; // 获取默认插槽const vnode = getFirstComponentChild(slot); // 得到插槽中的第一个组件的 vnodeconst name = getComponentName(vnode.componentOptions); // 获取组件名字const { cache, keys } = this; // 获取当前的缓存对象和key数组const key = ...; // 获取组件的key值,若没有,会按照规则自动生成if (cache[key]) {// 有缓存// 关键:重用组件实例vnode.componentInstance = cache[key].componentInstanceremove(keys, key); // 删除key// 将 key加入到数组末尾,这样是为了保证最近使用的组件在数组中靠后,反之靠前keys.push(key); } else {// 无缓存,则进行缓存cache[key] = vnodekeys.push(key)if (this.max && keys.length > parseInt(this.max)) {// 超过最大缓存数量,移除第一个key对应的缓存pruneCacheEntry(cache, keys[0], keys, this._vnode)}}return vnode || (slot && slot[0])
}

注意到,render() 返回的就是插槽中的第一个组件的 vnode。所以页面上显示的也就是这个子组件。

3,使用场景

在后台管理系统中比较常见,比如有2种情况就会用到:

  • 侧边栏的菜单,一般对应的是路由。切换页面(路由)时想保留之前的页面信息。
  • 列表页进详情页时,想保留列表页信息,因为列表可能是通过输入框等多个过滤条件得到的,如果从详情页返回列表页再次操作会比较繁琐。

这2种情况,都可以做成 tab 选项卡。

3.1,效果展示

在这里插入图片描述

3.2,实现思路

首先维护一个【tab选项卡】的状态,比如放到 Vuex 中。不放到组件内部,是因为不好使用,因为可能不止侧边栏会添加 tab,其他地方可能也会添加页面到 tab 选项卡。

export default new Vuex.Store({modules: {tabs: {namespaced: true,state: {pageNames: [] // 选项卡的页面},mutations: {addPage(state, newPageName) {if (!state.pageNames.includes(newPageName)) {state.pageNames.push(newPageName)}},removePage(state, pageName) {const index = state.pageNames.indexOf(pageName)if (index >= 0) {state.pageNames.splice(index, 1)}}}}}
})

其他的看代码就一目了然了:(省略了CSS)

<template><div><!-- 固定在页面左侧 --><div><h1>侧边栏</h1><ul><router-linkv-for="item in $router.options.routes":key="item.path"tag="li":to="{ name: item.name }"active-class="blue"><span>{{ item.name }}</span><button @click="handleAddPage(item.name)">+</button></router-link></ul></div><!-- 页面内容区域 --><div><!-- 固定在页面顶部,左侧和侧边栏对齐 --><div v-if="$store.state.tabs.pageNames.length"><span>tab选项卡:</span><ul><router-linkv-for="pageName in $store.state.tabs.pageNames":key="pageName"tag="li"active-class="green":to="{ name: pageName }"><span>{{ pageName }}</span><button @click="handleRemovePage(pageName)">x</button></router-link></ul></div><!-- 页面内容展示区域 --><keep-alive :include="$store.state.tabs.pageNames"><router-view></router-view></keep-alive></div></div>
</template><script>
export default {methods: {handleAddPage(pageName) {this.$store.commit('tabs/addPage', pageName)},handleRemovePage(pageName) {this.$store.commit('tabs/removePage', pageName)}}
}
</script>

以上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/645594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Golang入门教程】如何使用Goland创建并运行项目

自然语言处理的发展 文章目录 自然语言处理的发展**前言**创建新项目编辑运行/调试配置编写并运行代码总结强烈推荐专栏集锦写在最后 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站: 人工…

【边缘计算】TA的基本概念,以及TA的挑战和机遇

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读文章&#xff01; 此篇是【话题达人】序列文章&#xff0c;这一次的话题是《边缘计算的挑战和机遇》 文章将以博主的角度进行讲述&#xff0c;理解和水平有限&#xff0c;不足之处&#xff0c;望指正。 目录 背景基本概念挑战…

使用DBSyncer同步Oracle11g数据到Mysql5.7中_实现全量数据同步和增量数据实时同步_操作过程---数据同步之DBSyncer工作笔记007

之前都是用mysql和Postgresql之间进行同步的,已经实现了数据的实时同步,现在要实现Oracle数据库到Mysql数据库的全量,以及增量同步. 因为之前配置的不对,这里架构名写成了orcl,所以导致,虽然能连接上,但是,在进行数据同步的时候,看不到表,所以这里说一下如何进行连接 这里,首先…

socket以及字节序

1. socket 介绍&#xff1a; 简介&#xff1a; 所谓 socket&#xff08; 套接字&#xff09;&#xff0c;就是对网络中不同主机上的应用进程之间进行双向通信的 端点的抽象。 一个套接字就是网络上进程通信的一端&#xff0c;提供了应用层进程利用网络协议交换数据的机制。从所…

Vulnhub靶机:FunBox 5

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;FunBox 5&#xff08;10.0.2.30&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/funb…

C# 将HTML网页、HTML字符串转换为PDF文件

将HTML转换为PDF可实现格式保留、可靠打印、文档归档等多种用途&#xff0c;满足不同领域和情境下的需求。本文将通过以下两个示例&#xff0c;演示如何使用第三方库Spire.PDF for .NET和QT插件在C# 中将Html 网页&#xff08;URL&#xff09;或HTML字符串转为PDF文件。 HTML转…

引领AI变革:边缘计算与自然语言处理结合的无尽可能

引言 讲到Ai&#xff0c;你第一时间会想到什么&#xff1f;是Chagpt和文心一言这样与人类交流自然的Ai生成式对话服务&#xff1f;还是根据关键字快速制图的Ai绘图&#xff1f;这些都是近年来人们所常知的Ai用途&#xff0c;我们今天来讲讲以自然语言处理为辅&#xff0c;在Ai赋…

在 Python 中使用 OpenCV 通过透视校正转换图像

在计算机视觉和图像处理领域&#xff0c;透视变换是一个强大的工具。它允许我们改变图像的视角以获得新的视点&#xff0c;通常用于校正扭曲或模拟不同的相机角度。本文将探讨一个 Python 脚本&#xff0c;该脚本使用计算机视觉领域流行的 OpenCV 库对图像执行透视变换。我们将…

01-TiDB概述

分布式关系型数据库 1、支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) &#xff1a;OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)解决方案 2、无限制的水平扩容或者缩容 3、兼容MySQL &#xf…

openresty 安装, nginx与 openresty

openresty VS nginx Nginx 是一款高性能的 Web 服务器和反向代理服务器&#xff0c;具备基础的功能如HTTP服务、负载均衡、反向代理以及动静分离等。它是许多互联网应用的核心组件&#xff0c;因其模块化和可扩展的设计而受到欢迎。1 OpenResty 是基于 Nginx 的 Web 平台&…

nodeJs+express+Vue+MongoDB

数据库【Sqlite3、MongoDB、Mysql】简介&小记 Sqlite3&#xff1a; SQLite3是一个轻量级的数据库系统&#xff0c;它被设计成嵌入式数据库。这意味着它是一个包含在应用程序中的数据库&#xff0c;而不是独立运行的系统服务。适用场景&#xff1a;如小型工具、游戏、本地…

ubuntu20根目录扩容

ubuntu根目录/ 或者 /home文件夹有时出现空间满了的情况&#xff0c;可以用gparted工具进行空间的重新分配。 首先&#xff0c;如果你是双系统&#xff0c;需要从windows系统下磁盘压缩分配一部分未使用的空间给ubuntu&#xff0c;注意压缩的空间要邻接ubuntu所在盘的位置。 …

力扣刷MySQL-第七弹(详细讲解)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;力扣刷题讲解-MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出…

【Flink-1.17-教程】-【五】Flink 中的时间和窗口(2)时间语义

【Flink-1.17-教程】-【五】Flink 中的时间和窗口&#xff08;2&#xff09;时间语义 1&#xff09;Flink 中的时间语义2&#xff09;时间语义的分类2.1.处理时间&#xff08;process time&#xff09;2.2.摄取时间&#xff08;ingestion time&#xff09;2.3.事件时间&#xf…

大创项目推荐 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

Webpack5 基本使用 - 3(完结)

环境区分 可以定义多个配置文件&#xff0c;通过 webpack-merge 合并配置文件。 安装 webpack-merge yarn add webpack-merge公共配置 // webpack.common.js const path require(path) const HtmlWebpackPlugin require(html-webpack-plugin)module.exports {entry: path…

外呼机器人有什么优势?

外呼机器人有什么优势&#xff1f;值得受到大多数电销企业的追捧&#xff01; 1、电话外呼效率高&#xff1a; 每天可拨打的电话数量是人工的5-10倍&#xff0c;人工一天只能拨打200-300通电话&#xff0c;机器人每天能打3000通电话以上&#xff0c;无须休息&#xff0c;按照…

Java-NIO篇章(4)——Reactor反应器模式

前面已经讲过了Java-NIO中的三大核心组件Selector、Channel、Buffer&#xff0c;现在组件我们回了&#xff0c;但是如何实现一个超级高并发的socket网络通信程序呢&#xff1f;假设&#xff0c;我们只有一台内存为32G的Intel-i710八核的机器&#xff0c;如何实现同时2万个客户端…

openGauss学习笔记-206 openGauss 数据库运维-常见故障定位案例-too many clients already

文章目录 openGauss学习笔记-206 openGauss 数据库运维-常见故障定位案例-too many clients already206.1 高并发报错“too many clients already”或无法创建线程206.1.1 问题现象206.1.2 原因分析206.1.3 处理办法 openGauss学习笔记-206 openGauss 数据库运维-常见故障定位案…

143基于matlab的2D平面桁架有限元分析

基于matlab的2D平面桁架有限元分析&#xff0c;可以改变材料参数&#xff0c;输出平面结构外形&#xff0c;各桁架应力&#xff0c;位移及作用力。可查看节点力&#xff0c;程序已调通&#xff0c;可直接运行。 143 matlab 平面桁架 有限元分析 桁架应力 (xiaohongshu.com)