vue3组件动态缓存与动态刷新
动态缓存
前言
在项目中,为了减少性能消耗,有时我们需要使用keep-alive把组件缓存起来,但是并不是所有组件都需要被缓存,那么如何控制那些组件需要缓存呢?主要使用到路由meta,路由前置守卫,vux,动态组件。
实现
APP.vue
<script setup>
import { ref,computed } from 'vue'
import { useRouter } from 'vue-router'
import { useAlertsStore } from './store/modules/app.js'
const store = useAlertsStore()
const includes = computed(()=>{
return store.$state.includes
})
const router = useRouter()
const tohome = ()=>{
router.push('/home')
}
const totest = ()=>{
router.push('/test')
}
</script>
<template>
<div>
<button @click="tohome">home</button>
<button @click="totest">test</button>
<router-view v-slot="{Component}">
<keep-alive :include="includes">
<component :is="Component"></component>
</keep-alive>
</router-view>
</div>
</template>
<style>
.bg {
background-color: pink;
}
</style>
路由index.js
import { createRouter, createWebHashHistory } from 'vue-router'
import { useAlertsStore } from '../store/modules/app.js'
const routes = [
{
path: '/',
redirect: '/home'
},
{
// 导入的.vue组件名必须和组件注册的名字一致 文件名最好全小写 组件首字母最好大写
path: '/home',
name: 'home',
component: () => import('../views/home.vue'),
meta: {
name: 'home',
keepAlive: true
}
},
{
path: '/test',
name: 'test',
component: () => import('../views/testtwo.vue'),
meta: {
name: 'test',
keepAlive: false
}
},
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
router.beforeEach((to, from, next) => {
const store = useAlertsStore()
if (to.meta.keepAlive && to.name) {
store.setincludes({ name: to.name })
}
next() // 如果没传next 可以不用调用next函数 也能跳转
})
export default router
vuex
state: () => {
return {
includes: [],
}
},
actions: {
// 添加需要缓存的组件
setincludes(payload) {
this.$state.includes = [...new Set([...this.$state.includes, payload.name])]
},
动态刷新
前言
组件已经被我们缓存了,自然也不会重新发起网络请求请求新的数据,但是在某些情况下我们需要被缓存起来的页面重新发起ajax请求数据,这又该如何实现呢?这里主要使用到了发布订阅的思想。
实现
我们可以写一个自定义hook来封装它。
useRefreshFun
import { useAlertsStore } from '../store/modules/app.js'
import { computed, onActivated, nextTick } from 'vue'
import { useRoute } from 'vue-router'
export default function () {
const refresh = (paramsList) => {
const store = useAlertsStore()
const refreshApiList = computed(() => store.$state.refreshApiList || [])
const refreshApiFun = (pageName) => {
//当前缓存页面没有配置刷新接口
if (!paramsList) return
//获取该缓存页面中的vuex的api列表
const current = refreshApiList.value.find(
(item) => item.pageName.toLocaleUpperCase() == pageName.toLocaleUpperCase()
)
// 无需要刷新的api
if (!current) return
current.funsName.forEach((funName) => {
//vuex中的当前页面缓存的api集合
const refitem = paramsList.find((refitem) => funName === refitem.name)
//如果方法存在则刷新
if (refitem !== undefined) refitem.funsName.forEach((fun) => fun())
})
nextTick(() => store.removeRefreshApi(pageName))
}
// 组件被激活
onActivated(() => {
const route = useRoute()
const pageName = route.name
refreshApiFun(pageName)
})
}
// 添加刷新api
const addRefreshList = (apiParams) => {
const store = useAlertsStore()
store.addRefreshApi(apiParams)
}
return {
refresh,
addRefreshList
}
}
vux
import { defineStore } from 'pinia'
// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts', {
state: () => {
return {
includes: [],
refreshApiList: []
}
},
actions: {
// 添加需要缓存的组件
setincludes(payload) {
this.$state.includes = [...new Set([...this.$state.includes, payload.name])]
},
// 添加需要刷新的api
addRefreshApi(payload) {
const refreshApiList = this.$state.refreshApiList || []
const current = refreshApiList.find((item) => item.pageName === payload.pageName)
if (current) {
const addFunNames = payload.funsName.filter((item) => !current.funsName.includes(item))
current.funsName.push(...addFunNames)
} else {
this.$state.refreshApiList.push({
pageName: payload.pageName,
funsName: payload.funsName
})
}
},
// 删除需要刷新的api
removeRefreshApi(pageName) {
const refreshApiList = this.$state.refreshApiList || []
const index = refreshApiList.findIndex((item) => item.pageName === pageName)
index !== -1 && this.$state.refreshApiList.splice(index, 1)
},
}
})
在页面中使用
home.vue写入需要刷新的接口
<template>
<div>
home
<div>
<p>{{ num }}</p>
<button @click="()=>num--">-</button>
<button @click="()=>num++">+</button>
</div>
</div>
</template>
<script setup name="home">
import { ref } from 'vue'
import useRefreshFun from '../hooks/useRefreshFun.js'
let num = ref(0)
const queryAll = ()=>{
num.value = 0
}
const { refresh } = useRefreshFun()
refresh([{name:'init',funsName:[queryAll]}])
</script>
<style scoped>
</style>
test.vue为触发刷新的组件
<template>
<div>
test
<div>
<p>{{ num }}</p>
<button @click="()=>num--">-</button>
<button @click="()=>num++">+</button>
<button @click="refresh">触发home组件动态刷新</button>
</div>
</div>
</template>
<script setup name="test">
import { ref } from 'vue'
import useRefreshFun from '../hooks/useRefreshFun.js'
let num = ref(0)
const { addRefreshList } = useRefreshFun()
const refresh = ()=>{
addRefreshList({ pageName: 'home', funsName: ['init'] })
}
</script>
<style scoped>
</style>
本文作者:yunChuans
本文链接:https://www.cnblogs.com/zychuan/p/17509951.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步