【Fantastic-admin 技术揭秘】页面组件刷新

《Fantastic-admin 技术揭秘》系列将带你了解 Fantastic-admin 这款框架各种功能的设计与实现。通过了解这些技术细节,你不光可以更轻松地使用 Fantastic-admin 这款框架,也可以在其他项目中使用这些技术。

你可以点击 这里 查看本系列的所有文章,也欢迎你在评论区留言告诉我你感兴趣的内容,或许下一篇文章就会带你揭秘其中的奥秘。

需求分析

页面刷新是很常见的一种用户行为,比如一些表单页面,用户填写了一半数据,这时候打算重新填写,就会通过刷新页面恢复到初始状态。

但直接刷新浏览器会触发整个应用的重新加载,这显然不是我们希望看到的,最好是只刷新当前页面对应的组件。

实现方案

既然是页面组件刷新,那就可以确定下几种方案:

方案一

因为后台框架是嵌套路由的结构,所以可以在共用的父组件里,通过 v-if 来重新渲染 RouterView 组件,达到刷新当前页面的效果。

vue 复制代码
<script setup lang="ts">
import { usePageStore } from '@/store/modules/page';

const { isRefresh } = usePageStore();
</script>

<template>
  <RouterView v-slot="{ Component, route }">
    <KeepAlive :include="keepAliveStore.list">
      <component v-if="!isRefresh" :is="Component" :key="route.fullPath" />
    </KeepAlive>
  </RouterView>
</template>
ts 复制代码
// store/modules/page.ts
export const usePageStore = defineStore('page', () => {
  const isRefresh = ref(false);

  function setRefresh() {
    isRefresh.value = true;

    nextTick(() => {
      isRefresh.value = false;
    });
  }

  return { isRefresh, setRefresh };
});

把是否刷新页面这个状态交给 store 来管理,这样就可以在需要刷新页面的时候,调用 setRefresh 方法,然后页面就会重新渲染。

但是,这个方案有个弊端,因为 RouterView 组件会搭配 KeepAlive 组件一起使用,所以重新渲染 RouterView 组件,会影响到 KeepAlive 组件的缓存效果,这显然不是我们希望看到的。

方案二

既然方案一的通过 v-if 来重新渲染组件的结果不符合预期,那就换一种思路,通过跳转到一个空白页面,再立马跳转回来,也能达到刷新当前页面的效果。

我们需要准备一个 reload 页面,并写进路由配置中:

vue 复制代码
<script setup lang="ts">
const router = useRouter()

onMounted(() => {
  router.go(-1)
})
</script>

<template>
  <div />
</template>
ts 复制代码
// 注意:reload 页面也必须是嵌套路由的结构,确保它和其他业务页面是共用同一个父组件的,这样才能保证在跳转到 reload 页面时,keep-alive 组件的缓存效果不会受到影响
{
  path: '/',
  component: () => import('@/layouts/index.vue'),
  children: [
    {
      path: 'reload',
      name: 'reload',
      component: () => import('@/views/reload.vue'),
      meta: {
        title: '刷新页面',
      },
    },
  ],
}

还有最后一步,如果当前路由页面是开启页面缓存的,那么在跳转到 reload 页面时,需要手动删除下当前页面在 keep-alive 中的缓存。

以上篇《精细化控制页面缓存》文章为例,需要在 router.afterEach 中判断进入的是否为 reload 页面,如果是,则删除当前页面在 keep-alive 中的缓存。

ts 复制代码
// 这段代码如果看不明白,可以先阅读上篇文章
router.afterEach((to, from) => {
  const keepAliveStore = useKeepAliveStore()
  if (to.fullPath !== from.fullPath) {
    if (to.meta.cache) {
      const componentName = to.matched.at(-1)?.components?.default.name
      if (componentName) {
        keepAliveStore.add(componentName)
      }
      else {
        console.warn('该页面组件未设置组件名,会导致缓存失效,请检查')
      }
    }
    if (from.meta.cache) {
      const componentName = from.matched.at(-1)?.components?.default.name
      if (componentName) {
        switch (typeof from.meta.cache) {
          case 'string':
            if (from.meta.cache !== to.name) {
              keepAliveStore.remove(componentName)
            }
            break
          case 'object':
            if (!from.meta.cache.includes(to.name as string)) {
              keepAliveStore.remove(componentName)
            }
            break
        }
        if (from.meta.noCache) {
          switch (typeof from.meta.noCache) {
            case 'string':
              if (from.meta.noCache === to.name) {
                keepAliveStore.remove(componentName)
              }
              break
            case 'object':
              if (from.meta.noCache.includes(to.name as string)) {
                keepAliveStore.remove(componentName)
              }
              break
          }
        }
        // ↓↓↓ 在这里进行处理 ↓↓↓
        // 如果进入的是 reload 页面,则将离开页面的缓存清空
        if (to.name === 'reload') {
          keepAliveStore.remove(componentName)
        }
      }
    }
  }
})

这会,已经能基本满足页面刷新的需求了。

但这个方案也并非完美,因为毕竟是跳转到一个空白页面再跳回来,即便关闭了页面切换动画,在视觉上还是会看到页面闪烁了一下。

但话又说回来,这个闪烁的效果,或许也能作为用户反馈的一种形式,让用户知道页面刷新了。

相关推荐
anOnion6 分钟前
构建无障碍组件之Carousel Pattern
前端·html·交互设计
ssshooter14 分钟前
Tauri 2 iOS 开发避坑指南:文件保存、Dialog 和 Documents 目录的那些坑
前端·后端·ios
Можно1 小时前
深入理解 ES6 Proxy:与 Object.defineProperty 的全面对比
前端·javascript·vue.js
Birdy_x1 小时前
接口自动化项目实战(1):requests请求封装
开发语言·前端·python
天天向上10243 小时前
vue el-table实现拖拽排序
前端·javascript·vue.js
柳杉3 小时前
Three.js × Blender:从建模到 Web 3D 的完整工作流深度解析
前端·javascript·数据可视化
reembarkation4 小时前
vue3中使用howler播放音频列表
前端·vue.js·音视频
手握风云-5 小时前
基于 Java 的网页聊天室(三)
服务器·前端·数据库
weixin199701080165 小时前
《识货商品详情页前端性能优化实战》
前端·性能优化
Forever7_5 小时前
重磅!Vue3 手势工具正式发布!免费使用!
前端·前端框架·前端工程化