vue-element-admin解决三级目录的KeepAlive缓存问题(详情版)

vue-element-admin解决三级目录的KeepAlive缓存问题(详情版)

本文章将从问题出现的角度看看KeepAlive的缓存问题,然后提出两种解决方法。本文章比较详细,如果只是看怎么解决,代码怎么改,请前往配置版。

一、解决问题之间,先理清问题出现的原因

①首先,观察一下“一级目录”和“二级目录”

通过vue devtools工具,截图如下。
可以看到,“一级目录”——Tab,可以缓存:
在这里插入图片描述

再看看,“二级目录”——DirectivePermission,也可以缓存:
在这里插入图片描述

可以发现,他们都在<App>——<Layout>——<AppMain>下,同时<KeepAlive>的include属性包含组件配置的“name”(如上面两图所示)。

②再看看,“三级目录”的情况

通过vue devtools工具,截图如下。
可以看到,“三级目录”——Menu1-1,不可以缓存:
在这里插入图片描述

看发现,其明细的不同,他在<App>——<Layout>——<AppMain>——<Menu1>下,比“一级目录”和“二级目录”多了<Menu1>。由于<KeepAlive>的include属性并不包含<Menu1>组件配置的name——“Menu1”,而是组件配置的name——“Menu1-1”(如下图),所有不缓存。更多<keep-alive>不缓存的原因,可以看个人的另一篇文章。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、解决问题

①添加<RouterViewKeepAlive>解决

这里,你可能想到。既然,“三级目录”不缓存的原因是“由于<KeepAlive>的include属性并不包含<Menu1>组件配置的name——‘Menu1’”。那我在的include属性上,始终包含“Menu1”就行了(网上已经早有人写过类似解决方法,本文章的该解决方法也是参考该文章——见该文章)。

  • 首先,添加<RouterViewKeepAlive>组件
    新目录:src\layout\components\RouterViewKeepAlive\RouterViewKeepAlive.vue

    <!-- 父级路由组件,用于二级路由上, 该二级可以被keep-alive缓存 -->
    <!-- 由于该二级可以被keep-alive缓存,所以其三级的内容将保存 -->
    <!-- 注意:面包屑关闭后,不会从KeepAlive的include属性清除 -->
    <template><div class="app-main"><router-view /></div>
    </template>
    <script>
    export default {name: 'RouterViewKeepAlive'
    }
    </script>
    <style lang="scss" scoped>.app-main {}
    </style>
    
  • 然后,在<AppMain>添加“cachedViews”计算属性上添加“RouterViewKeepAlive”
    目录:src\layout\components\AppMain.vue

    <script>
    export default {name: 'AppMain',computed: {cachedViews() {// return this.$store.state.tagsView.cachedViews// 加入RouterViewKeepAlive组件,总是缓存二级目录路由配置为“RouterViewKeepAlive”的return ['RouterViewKeepAlive', ...this.$store.state.tagsView.cachedViews]},key() {return this.$route.path}}
    }
    </script>
    
  • 最后,修改路由配置(以原项目Nested Routes路由配置nested.js为例)
    目录:src\router\modules\nested.js

    /** When your routing table is too long, you can split it into small modules **/import Layout from '@/layout'
    // 导入RouterViewKeepAlive
    import RouterViewKeepAlive from '@/layout/components/RouterViewKeepAlive/RouterViewKeepAlive.vue'const nestedRouter = {path: '/nested',component: Layout,redirect: '/nested/menu1/menu1-1',name: 'Nested',meta: {title: 'Nested Routes',icon: 'nested'},children: [{path: 'menu1',// component: () => import('@/views/nested/menu1/index'), // Parent router-viewcomponent: RouterViewKeepAlive, // 使用RouterViewKeepAlive作为二级组件// name: 'Menu1',name: 'RouterViewKeepAlive', // 名字改为“RouterViewKeepAlive”,虽然没必要,但为了维护性meta: { title: 'Menu 1' },redirect: '/nested/menu1/menu1-1',children: [{path: 'menu1-1',component: () => import('@/views/nested/menu1/menu1-1'),name: 'Menu1-1',meta: { title: 'Menu 1-1' }},{path: 'menu1-2',component: () => import('@/views/nested/menu1/menu1-2'),name: 'Menu1-2',redirect: '/nested/menu1/menu1-2/menu1-2-1',meta: { title: 'Menu 1-2' },children: [{path: 'menu1-2-1',component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),name: 'Menu1-2-1',meta: { title: 'Menu 1-2-1' }},{path: 'menu1-2-2',component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),name: 'Menu1-2-2',meta: { title: 'Menu 1-2-2' }}]},{path: 'menu1-3',component: () => import('@/views/nested/menu1/menu1-3'),name: 'Menu1-3',meta: { title: 'Menu 1-3' }}]},{path: 'menu2',name: 'Menu2',component: () => import('@/views/nested/menu2/index'),meta: { title: 'Menu 2' }}]
    }export default nestedRouter

    注意:由于配置了“component: RouterViewKeepAlive”,使用了<RouterViewKeepAlive>作为二级组件,替换了’@/views/nested/menu1/index’的<Menu1>组件。

  • 结果
    可以看到“三级或以上的目录”被成功缓存了
    在这里插入图片描述

注意:这种实现方式存在弊端,就是永远关不掉(TagsView上的关闭),会一直占用内存
在这里插入图片描述

②转变Router配置解决

现在方法一,存在“关闭面包屑却不会关闭该缓存,会一直占用内存”的弊端,那怎么解决呢?
那找一下关闭<keep-alive>缓存的方法,不就解决了吗?
由于vue-element-admin项目是通过<keep-alive>的include来完成的,include如果没有加上“RouterViewKeepAlive”,就会将所有的<RouterViewKeepAlive>没缓存,这不是我们想要的。我们想要的是“缓存对应key的<RouterViewKeepAlive>,然后移除对应key的<RouterViewKeepAlive>”。
但是,个人看了官网并未提供或暴露这种特殊的方法接口。

那现在我们换一种思路——“注册路由时,将三级或以上的路由配置转换为一级和二级的那样”,如下图:
在这里插入图片描述
由于vue-element-admin项目在左侧菜单栏等地方用到了@/store的permission.js的“routes”。所以,现在的思路是“只改变Router的挂载,其他保持不改”,步骤如下。

  • 首先,对permission.js,添加flattenRoutes方法和修改generateRoutes
    目录:src\store\modules\permission.js

    // ...
    /*** 将单个路由,假如有三级或三级目录,则转为二级目录格式* @param {Object} router 要处理的路由* @returns {Object} 处理后的路由*/
    function flattenRouter(router) {// 创建一个新的对象来存储转换后的路由const newRouter = {...router,children: []}const routerChildren = router.children// 从根路由开始扁平化if (routerChildren && routerChildren.length > 0) {flatten('', routerChildren)}/*** 递归函数来遍历和扁平化路由* @param {String} parentPath 父路由路径* @param {Array} routes 路由*/function flatten(parentPath, routes) {routes.forEach(route => {const { path, children } = route// 构建完整的路径const fullPath = `${parentPath}${path.startsWith('/') ? path.slice(1) : path}`// 如果当前路由有子路由,则递归处理if (children && children.length > 0) {flatten(`${fullPath}/`, children)} else {// 否则,将当前路由添加到新的children数组中newRouter.children.push({...route,path: fullPath})}})}return newRouter
    }/*** 处理路由,将三级或三级以上目录的转为二级目录格式* @param {Array} routes routes* @param {Array} 处理后的路由*/
    export function flattenRoutes(routes) {const res = []routes.forEach(route => {const newRouter = flattenRouter(route)res.push(newRouter)})return res
    }// ...
    const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {let accessedRoutesif (roles.includes('admin')) {accessedRoutes = asyncRoutes || []} else {accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)}// 处理路由,将三级或三级以上目录的转为二级目录格式const flattenAccessedRoutes = flattenRoutes(accessedRoutes)// store存的是accessedRoutes,用于左侧边导航栏,多级目录(包含三级或以上)commit('SET_ROUTES', accessedRoutes)// resolve(accessedRoutes)// Promise的resolve出去的是flattenAccessedRoutes,用于路由,多级目录(已转换为二级目录格式,不包含三级或以上)resolve(flattenAccessedRoutes)})}
    }
    // ...
    

    完整代码如下:

    import { asyncRoutes, constantRoutes } from '@/router'/*** Use meta.role to determine if the current user has permission* @param roles* @param route*/
    function hasPermission(roles, route) {if (route.meta && route.meta.roles) {return roles.some(role => route.meta.roles.includes(role))} else {return true}
    }/*** Filter asynchronous routing tables by recursion* @param routes asyncRoutes* @param roles*/
    export function filterAsyncRoutes(routes, roles) {const res = []routes.forEach(route => {const tmp = { ...route }if (hasPermission(roles, tmp)) {if (tmp.children) {tmp.children = filterAsyncRoutes(tmp.children, roles)}res.push(tmp)}})return res
    }/*** 将单个路由,假如有三级或三级目录,则转为二级目录格式* @param {Object} router 要处理的路由* @returns {Object} 处理后的路由*/
    function flattenRouter(router) {// 创建一个新的对象来存储转换后的路由const newRouter = {...router,children: []}const routerChildren = router.children// 从根路由开始扁平化if (routerChildren && routerChildren.length > 0) {flatten('', routerChildren)}/*** 递归函数来遍历和扁平化路由* @param {String} parentPath 父路由路径* @param {Array} routes 路由*/function flatten(parentPath, routes) {routes.forEach(route => {const { path, children } = route// 构建完整的路径const fullPath = `${parentPath}${path.startsWith('/') ? path.slice(1) : path}`// 如果当前路由有子路由,则递归处理if (children && children.length > 0) {flatten(`${fullPath}/`, children)} else {// 否则,将当前路由添加到新的children数组中newRouter.children.push({...route,path: fullPath})}})}return newRouter
    }/*** 处理路由,将三级或三级以上目录的转为二级目录格式* @param {Array} routes routes* @param {Array} 处理后的路由*/
    export function flattenRoutes(routes) {const res = []routes.forEach(route => {const newRouter = flattenRouter(route)res.push(newRouter)})return res
    }const state = {routes: [],addRoutes: []
    }const mutations = {SET_ROUTES: (state, routes) => {state.addRoutes = routesstate.routes = constantRoutes.concat(routes)}
    }const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {let accessedRoutesif (roles.includes('admin')) {accessedRoutes = asyncRoutes || []} else {accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)}// 处理路由,将三级或三级以上目录的转为二级目录格式const flattenAccessedRoutes = flattenRoutes(accessedRoutes)// store存的是accessedRoutes,用于左侧边导航栏,多级目录(包含三级或以上)commit('SET_ROUTES', accessedRoutes)// resolve(accessedRoutes)// Promise的resolve出去的是flattenAccessedRoutes,用于路由,多级目录(已转换为二级目录,不包含三级或以上)resolve(flattenAccessedRoutes)})}
    }export default {namespaced: true,state,mutations,actions
    }
    
  • 然后,进行测试
    更改文件如下:
    修改nested.js的name:‘Menu1-1’→’Menu11’。同理,‘Menu12’、‘Menu121’、‘Menu122’、‘Menu13’。
    目录:src\router\modules\nested.js

    /** When your routing table is too long, you can split it into small modules **/import Layout from '@/layout'const nestedRouter = {path: '/nested',component: Layout,redirect: '/nested/menu1/menu1-1',name: 'Nested',meta: {title: 'Nested Routes',icon: 'nested'},children: [{path: 'menu1',// component: () => import('@/views/nested/menu1/index'), // Parent router-viewname: 'Menu1',meta: { title: 'Menu 1' },redirect: '/nested/menu1/menu1-1',children: [{path: 'menu1-1',component: () => import('@/views/nested/menu1/menu1-1'),name: 'Menu11', // 已更改,便于测试meta: { title: 'Menu 1-1' }},{path: 'menu1-2',// component: () => import('@/views/nested/menu1/menu1-2'),name: 'Menu12', // 已更改,便于测试redirect: '/nested/menu1/menu1-2/menu1-2-1',meta: { title: 'Menu 1-2' },children: [{path: 'menu1-2-1',component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),name: 'Menu121', // 已更改,便于测试meta: { title: 'Menu 1-2-1' }},{path: 'menu1-2-2',component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),name: 'Menu122', // 已更改,便于测试meta: { title: 'Menu 1-2-2' }}]},{path: 'menu1-3',component: () => import('@/views/nested/menu1/menu1-3'),name: 'Menu13', // 已更改,便于测试meta: { title: 'Menu 1-3' }}]},{path: 'menu2',name: 'Menu2',component: () => import('@/views/nested/menu2/index'),meta: { title: 'Menu 2' }}]
    }export default nestedRouter
    

    修改‘menu1-1\index.vue’,添加和nested.js配置一样的name属性。同理,‘menu1\menu1-2\menu1-2-1\index.vue’、‘menu1\menu1-2\menu1-2-2\index.vue’、‘menu1\menu1-3\index.vue’(注意:同时,将开头的“<template functional>”改为“<template>”)。
    以menu1-1为例,代码如下,其他的同理。
    目录:src\views\nested\menu1\menu1-1\index.vue

    <template><div style="padding: 30px"><el-alert :closable="false" title="menu 1-1" type="success"><router-view /></el-alert></div>
    </template>
    <!-- 修改后 -->
    <script>
    export default {// 添加name属性,让keep-alive进行缓存name: 'Menu11'
    }
    </script>
    
  • 结果
    可以看到“三级或以上的目录”被成功缓存了
    在这里插入图片描述

注意事项:
①与方法一“添加<RouterViewKeepAlive>解决”的区别:
方法一是“使用了<RouterViewKeepAlive>作为二级组件,替换了’@/views/nested/menu1/index’的<Menu1>组件。”;
而方法二是“扁平化路由”,就如上方测试改nested.js那样,一些“component”的配置是没意义的,所以注释掉了
这种实现方式同样存在弊端,就是Breadcrumb 面包屑多级关系不见了。因为,由于vue-element-admin项目Breadcrumb 面包屑是通过$route来实现的,而我们恰好改的就是路由配置。区别如下:
在这里插入图片描述
在这里插入图片描述
③上面,添加flattenRoutes方法只是对“accessedRoutes”做了处理,还未对“constantRoutes”处理,比如同时对“constantRoutes”处理。处理代码如下:
目录:src\router\index.js

// ...
/* 处理路由 */
import { flattenRoutes } from '@/store/modules/permission'// ...
const createRouter = () => new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),// routes: constantRoutes// 处理路由,将三级或三级以上目录的转为二级目录格式routes: flattenRoutes(constantRoutes)
})
// ...

③直接移除include解决

此方法官方文档此次提到“前往@/layout/components/AppMain.vue文件下,移除include相关代码即可。当然直接使用 keep-alive 也是有弊端的,他并不能动态的删除缓存,你最多只能帮它设置一个最大缓存实例的个数 limit。

更改如下:
目录:src\layout\components\AppMain.vue

<template><section class="app-main"><transition name="fade-transform" mode="out-in"><!-- 移除include --><!-- <keep-alive :include="cachedViews"> --><keep-alive><router-view :key="key" /></keep-alive></transition></section>
</template>
// ...

如果,想要设置最大缓存个数,比如设置最大10个。只需将“<keep-alive>”改为“<keep-alive :max=“10”>”

注意事项:
①该方法的弊端:官方文档说的也很清楚了——“他并不能动态的删除缓存,只能帮它设置一个最大缓存实例的个数”。
②与方法一的对比:没使用了<RouterViewKeepAlive>作为二级组件,替换了’@/views/nested/menu1/index’的<Menu1>组件;该方法的“他并不能动态的删除缓存”的范围比方法一的范围大,该方法所有的目录都不能动态删除缓存,而方法一是三级或以上的目录不能移除。
③与方法二的对比:没“扁平化路由”无方法二的弊端——Breadcrumb 面包屑多级关系不见了

三、总结

vue-element-admin解决三级目录的KeepAlive缓存问题:
①添加<RouterViewKeepAlive>解决
弊端:永远关不掉(TagsView上的关闭),会一直占用内存
(可以给keep-alive设置一个最大缓存实例的个数,但不一定满足项目需求;如果该项目三级或以上的目录不多,就几个,那还能接受内存的占用)

②转变Router配置解决
弊端:Breadcrumb 面包屑多级关系不见了
(如果真实项目,无需“Breadcrumb 面包屑”同时最多三级(见方法二的“注意事项”),还可以接受。)

③直接移除include解决
弊端:他并不能动态的删除缓存,只能帮它设置一个最大缓存实例的个数
(如果真实项目,可以接受“不能动态的删除缓存”和“设置最大缓存实例的个数”的弊端,那该方法是最简单的解决方法。)

这里强调一下:由于上述方法是对原本vue-element-admin项目构建上的修复,一旦按照文章修复了,一定要记得项目的可维护性,不然,下一个接手该项目的码农将会很疑惑。比如,在真实项目的“README.md”上添加修改的文字描述和路由配置注意事项,同时在src\router\index.js的路由配置上注释好。

最终,似乎都没有十全十美的解决方案,每一种方案总是存在一些“舍去”。就vue-element-admin的作者在文档提过“如果没有标签导航栏需求的用户,建议移除此功能”。

网上也有更多的解决方法,比如:

  • 使用created解决
  • 设置hidden:true隐藏

如果想了解更多关于vue-element-admin项目<keep-alive>不缓存的原因,也欢迎看看个人的另一篇文章。
如果大家有其他更完美的解决方案或者本文章方法的不足之处,欢迎在评论区讨论!

四、参考文献

  • sweet202005——解决vue项目三级菜单路由无法缓存问题
  • Vue2——keep-alive

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

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

相关文章

零工市场小程序应该有什么功能?

数字经济现如今正飞速发展&#xff0c;零工市场小程序在连接雇主与自由职业者方面发挥着越来越重要的作用。一个高效的零工市场小程序不仅需要具备基础的信息发布与匹配功能&#xff0c;还应该涵盖交易管理、安全保障以及个性化服务等多个方面。 那么&#xff0c;零工市场小程…

Ubuntu22.04下安装LDAP

目录 1 简单说明2 安装配置2.1 安装1、安装前准备2、安装 OpenLADP3、配置OpenLDAP4、设置基本组5、添加新组5、添加 OpenLDAP 用户 2.2 安装 LDAP 帐户管理器1、安装2、配置 LDAP 帐户管理器 3 简单使用3.1 创建一个组3.2 创建一个用户 总结 1 简单说明 之前写过在Centos下的…

nginx和tomcat负载均衡,动静分离

文章目录 一&#xff0c;tomcat1.tomca用途2.tomcat重要目录 二&#xff0c;nginx1.Nginx应用2.nginx作用3.nginx的正向代理和反向代理3.1正向代理3.2反向代理(单级)3.3反向代理(多级) 4.nginx负载均衡4.1Nginx支持的常见的分流算法1. 轮询(Round Robin):2.最少连接数(LeastCon…

[MRCTF2020]Hello_ misc

解压得一个png图片和一个flag.rar 图片拖入010editor 选择带zip头的这段蓝色全部复制&#xff0c;file-new-new Hex File&#xff0c;黏贴到新文件&#xff0c;另存为为1.zip 要密码,线索中断&#xff08;当然try to restore it.png&#xff0c;隐藏了zip压缩包&#xff0c;可…

uniapp - plugins的组件配置使用

点击进入到uniapp中mp-weixin的配置中 点击进入小程序的plugin的配置 在项目中&#xff0c;我们可引用插件的使用&#xff0c;例如一些快递100&#xff0c;点餐插件的业务引入 添加插件 在使用插件前&#xff0c;首先要在小程序管理后台的“设置-第三方服务-插件管理”中添加…

java ssl使用自定义证书或忽略证书

1.证书错误 Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 2.生成客户端证书 openssl x509 -in <(openssl s_client -connect 192.168.11.19:8101 -prexit 2>/dev/null) -ou…

C HTML格式解析与生成

cmake报错替换 if(NOT MyHTML_BUILD_WITHOUT_THREADS OR NOT MyCORE_BUILD_WITHOUT_THREADS) set(CMAKE_THREAD_PREFER_PTHREAD 1) if (WIN32) set(CMAKE_USE_WIN32_THREADS_INIT ON) set(CMAKE_THREAD_PREFER_PTHREADS TRUE) set(THREADS_PR…

windows配置jmeter定时任务

场景&#xff1a; 需要让脚本在指定的执行 步骤&#xff1a; 准备jmeter脚本&#xff0c;保证在命令行中可以调用脚本且脚本运行正常&#xff1a;"C:\Apache\jmeter\bin\jmeter.bat" -n -t C:\tests\test_plan.jmx -l C:\tests\results.jtl -t : 指定执行jmeter脚…

异步交互技术Ajax-Axios

目录 一、同步交互和异步交互 二、Ajax 1.概述 2.如何实现ajax请求 三、异步传输数据乱码的问题 regist.html页面代码 服务端代码处理 四、Axios 1. Axios的基本使用 &#xff08;1&#xff09;引入Axios文件 &#xff08;2&#xff09;使用Axios发送请求&#xff0…

通过Python绘制不同数据类型适合的可视化图表

在数据可视化中&#xff0c;对于描述数值变量与数值变量之间的关系常见的有散点图和热力图&#xff0c;以及描述数值变量与分类变量之间的关系常见的有条形图&#xff0c;饼图和折线图&#xff0c;可以通过使用Python的matplotlib和seaborn库来绘制图表进行可视化表达&#xff…

【大数据】什么是数据中台?

随着企业规模不断扩大、业务多元化——中台服务架构的应运而生。“中台”早期是由美军的作战体系演化而来的&#xff0c;技术上说的“中台”主要是指学习这种高效、灵活和强大的指挥作战体系。阿里在今年发布“双中台ET”数字化转型方法论&#xff0c;“双中台”指的是数字中台…

ResNet网络学习

简介 Residual Network 简称 ResNet (残差网络) 下面是ResNet的网络结构&#xff1a; ResNet详细介绍 原理 传统方法的问题&#xff1a; 对于一个网络&#xff0c;如果简单地增加深度&#xff0c;就会导致 梯度消失 或 梯度爆炸&#xff0c;我们采取的解决方法是 正则化。…

卸载nomachine

网上的方法:提示找不到命令 我的方法: step1. 终端输入 sudo find / -name nxserver 2>/dev/null确认 NoMachine 的实际安装路径。你可以使用 find 命令在系统中查找 nxserver 脚本的位置。 找到路径后,你可以使用该路径来卸载 NoMachine。 如下图,紫色框中是我的路径…

ProtoBuf简要介绍与快速上手使用(C++版)

文章目录 一、 初识ProtoBuf1. 序列化和反序列化概念2. ProtoBuf是什么3. ProtoBuf的使用特点 二、 讲解说明三、 快速上手1. 创建 .proto 文件2. 编译 contacts.proto 文件&#xff0c;生成C文件3. 序列化与反序列化的使用4. 小结 ProtoBuf 使用流程 一、 初识ProtoBuf 1. 序…

Linux权限维持实战

目录 介绍步骤 介绍 攻击者在获取服务器权限后&#xff0c;会通过一些技巧来隐藏自己的踪迹和后门文件 查看/tmp目录下的flag文件 查看/root目录下具有特殊文件属性的文件 操作机中共有几个SUID文件 操作机中共有几个SGID文件 查看操作机中ssh公私钥免密登陆 查看strace后门 …

Web3链上聚合器声呐已全球上线,开启区块链数据洞察新时代

在全球区块链技术高速发展的浪潮中&#xff0c;在创新发展理念的驱动下&#xff0c;区块链领域的工具类应用备受资本青睐。 2024年8月20日&#xff0c;由生纳&#xff08;香港&#xff09;国际集团倾力打造的一款链上应用工具——“声呐链上聚合器”&#xff0c;即“声呐链上数…

24暑假算法刷题 | Day39 | 动态规划 VII | LeetCode 198. 打家劫舍,213. 打家劫舍 II,337. 打家劫舍 III

目录 198. 打家劫舍题目描述题解 213. 打家劫舍 II题目描述题解 337. 打家劫舍 III题目描述题解 打家劫舍的一天 &#x1f608; 198. 打家劫舍 点此跳转题目链接 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷…

贪心+栈。。

前言&#xff1a;这个题目一开始我没想通的就是如果s当前的一个字符或者之后的一个字符和当前t的尾巴是一样的&#xff0c;那么优先选哪一个&#xff0c;其实这个就要优先选t的 class Solution { public:string robotWithString(string s) {string ans;int cnt[26]{}, min 0; …

<C++> 二叉搜索树

目录 二叉搜索树 1. 概念 2. 二叉搜索树操作 2.1 基础结构 2.2 非递归版 1. 查找 2. 插入 3. 删除 2.3 递归版 1. 查找 2. 插入 3. 删除 2.4 拷贝构造函数 2.5 赋值运算符重载 2.6 析构函数 2.7 完整代码 3. 二叉搜索树的应用 4. 二叉搜索树的性能 二叉搜索树 1. 概念 二叉搜索…

SpringBoot+Vue3整合minio,实现分布式文件存储

文章目录 几种常用的文件存储安装和使用minioSpringBoot整合minio 基本所有的软件项目都会需要文件存储功能&#xff0c;图片、视频存储。 几种常用的文件存储 经常用的几种方案&#xff0c;直接存在本地文件夹&#xff0c;开发一个简单的系统当然没有问题。随机系统所需的资源…