- API 路由统一: 移除 /api/h5/,统一 /api/pms/ 入口 - 二进制改名: api-server -> pms-api(与服务名一致) - nginx: 合并 /api/ + /pms/api/ 为 /api/pms/ - 新增 docs/API.md 接口文档 - 后端: CabinetDetail 增加 rssi/pow_fail/address/soc 等字段 - Redis 管道批量读取仓体实时数据(SOC/电压/电流/功率) - DB: 所有 TIMESTAMP 列改为 DATETIME(修复类型不匹配) - 用户管理: 新增创建时间/修改时间列,状态改用 Switch - 角色管理/用户管理: 操作按钮改为图标 - PC 设备详情: 基本信息补全 RSSI/ICCID/电源/地址 - PC 卡片: 通道统计改用 Lucide 图标,颜色统一 - PC 二维码: canvas 渲染,含编号文字,支持右键下载 - H5: 按 uni-app 规范修正导航(navigateTo 替代 reLaunch) - H5: 详情页加返回导航条 - H5: 扫码支持摄像头(jsQR)+ ?id= 参数 - H5: 底部 tabBar 在所有页面常显 - H5: 首页统计改为 6 项(设备/通道/空闲/充电/充满/故障) - H5: 下拉刷新 / 上拉加载 - 产品首页: 添加业务联系 - 文档: 清理过时文件,补充缺失规范章节
4.5 KiB
4.5 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Vue 3 KeepAlive Has No Direct Cache Removal API | MEDIUM | Unlike Vue 2, there is no way to programmatically remove a specific component from KeepAlive cache in Vue 3 | gotcha |
|
Vue 3 KeepAlive Has No Direct Cache Removal API
Impact: MEDIUM - Vue 3 removed the $destroy() method that Vue 2 developers used to indirectly clear KeepAlive cache entries. There is no direct API to remove a specific cached component in Vue 3.
Task Checklist
- Do not rely on programmatic cache removal from Vue 2 patterns
- Use
include/excludeprops for dynamic cache control - Use key changes to force cache invalidation
- Set appropriate
maxprop to auto-evict old entries
The Problem
Vue 2 Pattern (No Longer Works)
// Vue 2: Could destroy specific component instance
this.$children[0].$destroy()
Vue 3: No Equivalent API
// Vue 3: $destroy() does not exist
// There is NO direct way to remove a specific cached instance
Solutions
Solution 1: Dynamic Include/Exclude
Control cache membership via reactive props:
<script setup>
import { ref, computed } from 'vue'
const cachedViews = ref(['Dashboard', 'Settings', 'Profile'])
function removeFromCache(viewName) {
cachedViews.value = cachedViews.value.filter(v => v !== viewName)
}
function addToCache(viewName) {
if (!cachedViews.value.includes(viewName)) {
cachedViews.value.push(viewName)
}
}
</script>
<template>
<KeepAlive :include="cachedViews">
<component :is="currentView" />
</KeepAlive>
</template>
When a component is removed from include, it will be destroyed on next switch.
Solution 2: Key-Based Cache Invalidation
Change the key to force a fresh instance:
<script setup>
import { ref, reactive } from 'vue'
const currentView = ref('Dashboard')
const viewKeys = reactive({
Dashboard: 0,
Settings: 0,
Profile: 0
})
function invalidateCache(viewName) {
viewKeys[viewName]++
}
function switchView(viewName) {
currentView.value = viewName
}
// Force fresh Dashboard on next visit
function refreshDashboard() {
invalidateCache('Dashboard')
}
</script>
<template>
<KeepAlive>
<component
:is="currentView"
:key="`${currentView}-${viewKeys[currentView]}`"
/>
</KeepAlive>
</template>
Solution 3: Conditional KeepAlive
Wrap or unwrap based on cache need:
<script setup>
import { ref } from 'vue'
const currentView = ref('Dashboard')
const shouldCache = ref(true)
function clearCacheAndSwitch(viewName) {
shouldCache.value = false
currentView.value = viewName
// Re-enable caching after the switch
nextTick(() => {
shouldCache.value = true
})
}
</script>
<template>
<KeepAlive v-if="shouldCache">
<component :is="currentView" />
</KeepAlive>
<component v-else :is="currentView" />
</template>
Solution 4: Use Max for Automatic Eviction
Let LRU cache handle cleanup:
<template>
<!-- Automatically evicts least recently used when cache is full -->
<KeepAlive :max="5">
<component :is="currentView" />
</KeepAlive>
</template>
Vue Router: Clear Cache on Certain Navigations
<script setup>
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const cachedRoutes = ref(['Dashboard', 'Settings'])
// Clear specific route from cache when navigating from certain paths
watch(() => route.name, (newRoute, oldRoute) => {
if (oldRoute === 'Login') {
// User just logged in - clear and refresh Dashboard
cachedRoutes.value = cachedRoutes.value.filter(r => r !== 'Dashboard')
nextTick(() => {
cachedRoutes.value.push('Dashboard')
})
}
})
</script>
<template>
<router-view v-slot="{ Component }">
<KeepAlive :include="cachedRoutes">
<component :is="Component" />
</KeepAlive>
</router-view>
</template>
Key Points
- No
$destroy()in Vue 3 - Cannot directly remove cached instances - Use dynamic
include- Reactively control which components are cached - Use key changes - Changing key creates a new cache entry
- Use
maxprop - LRU eviction handles cleanup automatically - Plan cache strategy - Design around these constraints upfront