需求:【详情页】返回【列表页】需缓存状态(分页,查询条件),其他页进入【列表页】不缓存
1、在路由表中设置meta中添加keepAlive标识
// 列表页
{
path: '/review-record-info',
name: 'reviewRecordInfo',
component: () => import('../views/reviewRecordInfo.vue'),
meta: {
keepAlive: true,
},
},
// 详情页
{
path: '/review-record-detail',
name: 'reviewRecordDetail',
component: () => import('../views/reviewRecordDetail.vue'),
meta: {
keepAlive: true,
},
}
2、列表页中添加路由拦截、并添加钩子函数
// views/reviewRecordInfo.vue 列表页
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
beforeRouteEnter(to, from, next) {
// 判断是否是详情页返回
if (from.path == '/review-record-detail') {
to.meta.isBack = true
} else {
to.meta.isBack = false
}
next()
},
})
</script>
<script setup lang="ts">
import { ref, onMounted, onActivated, onDeactivated } from 'vue'
const { pagination } = usePagination()
const [formData, change] = useListParam(form)
const { listData, refreshData, selection } = useDataList({
listApi: serverApi.use('GET:/kqcs/system/bizTemplate/list'),
paramGroups: [formData, pagination.value.params],
})
onMounted(() => {
isFirst.value = true
})
onActivated(() => {
if (isFirst.value || route.meta.isBack ) return
// 参数清空 重新请求数据
form.templateName = ''
pagination.value.params.pageNum = 1
change(JSON.parse(JSON.stringify(form)))
})
onDeactivated(() => {
isFirst.value = false
})
</script>
3、给组件有条件添加keep-alive标签
<router-view v-slot="{ Component }">
<keep-alive :include="includeList">
<component :is="Component" :key="route.path"></component>
</keep-alive>
</router-view>
export default defineComponent({
setup() {
const router = useRouter()
const includeList = computed(
() =>
router
.getRoutes()
.filter((i) => i.meta.keepAlive)
.map((i) => i.name) as string[]
)
return { includeList, route }
},
})
</script>
includeList中的name会根据组件的name进行匹配, 所以组件想要有条件被KeepAlive缓存,就必须显式生命一个name选项。
Tip:在 3.2.34 或以上的版本中,使用 <script setup 语法糖的单文件组件会自动根据文件名生成对应的 name 选项,无需再手动声明。
以上情况只考虑到查看返回的场景,但在项目中新增、编辑、查看用的同一个页面,所以需根据用户的具体操作做不同处理,从详情页返回有以下三种情况:
1、查看:【详情页】返回【列表页】需缓存数据,不做任何操作;
2、编辑:【详情页】返回【列表页】需缓存数据,重新请求接口;
3、新增:【详情页】返回【列表页】不需要缓存数据,并需要置空查询条件和分页重新请求接口。
在详情页操作时给列表页meta添加操作标识
// views/reviewRecordDetail.vue 详情页
// 新增
async function createTemplateInfo(params) {
await serverApi.use('POST:/kqcs/system/bizTemplate/bizTemplateAdd')(params)
ElMessage.success('操作成功')
router.push('/review-template-mgt')
route.meta.action = ActionEnum.ADD
}
//编辑
async function editTemplateInfo(params) {
await serverApi.use('POST:/kqcs/system/bizTemplate/bizTemplateEdit')(params)
ElMessage.success('保存成功')
router.push('/review-template-mgt')
route.meta.action = ActionEnum.EDIT
}
列表页获取route meta中的操作标识处理数据
// views/reviewRecordInfo.vue 列表页
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
beforeRouteEnter(to, from, next) {
if (from.path == '/review-template-detail') {
to.meta.isBack = true
to.meta.action = from.meta.action
} else {
to.meta.isBack = false
}
next()
},
})
</script>
// isFirst为了记录是否是初次进入页面 避免初始化页面调用两次bizTemplate/list接口
const isFirst = ref(false)
const [form, change] = useListParam(formData)
// 此处是自己封装的useDataList, 进入页面则会请求接口
const { listData, refreshData, selection } = useDataList({
listApi: serverApi.use('GET:/kqcs/system/bizTemplate/list'),
paramGroups: [form, pagination.value.params],
})
onMounted(() => {
isFirst.value = true
})
onActivated(() => {
if (isFirst.value) return
// 不是从详情页返回,或者新增成功,则清空数据重新请求
if (!route.meta.isBack || route.meta.action === ActionEnum.ADD) {
formData.templateName = ''
pagination.value.params.pageNum = 1
change(JSON.parse(JSON.stringify(formData)))
}
// 编辑成功后,保留查询条件、分页参数,重新请求列表
if (route.meta.action === ActionEnum.EDIT) {
change(JSON.parse(JSON.stringify(formData)))
}
})
onDeactivated(() => {
isFirst.value = false
})