• Vue3实现刷新页面局部内容


    想要实现页面的局部刷新,我们只需要实现局部组件(dom)的重新渲染。在Vue中,想要实现这一效果最简便的方式方法就是使用v-if 指令。

    在Vue2中我们除了使用v-if 指令让局部dom的重新渲染,也可以新建一个空白组件,需要刷新局部页面时跳转至这个空白组件页面,然后在空白组件内的beforeRouteEnter 守卫中又跳转回原来的页面。

    如下图所示,如何在Vue3.X中实现点击刷新按钮实现红框范围内的dom重新加载,并展示对应的加载状态。

    在这里插入图片描述

    在这里插入图片描述

    由于Vue3.X中script setup 语法中组件内守卫只有onBeforeRouteUpdateonBeforeRouteUpdate 两个API,因此我们来借助v-if 指令使局部dom重新渲染来实现这一需求。

    第一步:定义状态标识

    在全局状态中定义一个isRouterAlive 标识刷新状态,根据isRouterAlive 变化来重新渲染。isLoading 标识加载状态。

    import { defineStore } from 'pinia'
    export const useAppStore = defineStore({
      id: 'app',
      state: () =>
        ({
          isRouterAlive: true,
          isLoading: false
        } as { isRouterAlive: boolean; isLoading: boolean })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第二步、借用v-if 指令让dom节点重新渲染

    <template>
      <div class="common-layout">
        <el-container>
          <SideMenuView :collapse="isCollapse"></SideMenuView>
          <el-container>
            <NavMenuView v-model:collapse="isCollapse"></NavMenuView>
            <TabsView></TabsView>
            <!--核心 start-->
            <el-main
              v-loading="appStore.isLoading"
              element-loading-text="页面加载中……"
              element-loading-background="rgba(0, 0, 0, 0.8)"
            >
              <router-view v-if="appStore.isRouterAlive"> </router-view>
            </el-main>
            <!--核心 end-->
            <el-footer>Footer</el-footer>
          </el-container>
        </el-container>
      </div>
    </template>
    
    <script setup lang="ts">
    import SideMenuView from './SideMenuView.vue'
    import NavMenuView from './NavMenuView.vue'
    import TabsView from './TabsView.vue'
    import { useAppStore } from '@/stores/app'
    const appStore = useAppStore()
    const isCollapse = ref(false)
    </script>
    
    <style lang="scss" scoped>
    …… CSS样式
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    第三步、修改isRouterAlive 值,实现dom的重新渲染

    <template>
      <div
        class="tabs-item cursor-pointer arrow-down"
        ref="buttonRef"
        @click="onClickOutside"
      >
        <el-icon><ArrowDownBold /></el-icon>
      </div>
      <el-popover
        ref="popoverRef"
        trigger="hover"
        virtual-triggering
        :virtual-ref="buttonRef"
      >
        <div class="arrow-down-item" @click="handleCommand('refresh')">刷新</div>
        <div class="arrow-down-item" @click="handleCommand('closeOther')">
          关闭其他
        </div>
        <div class="arrow-down-item" @click="handleCommand('closeLeft')">
          关闭左侧
        </div>
        <div class="arrow-down-item" @click="handleCommand('closeRight')">
          关闭右侧
        </div>
      </el-popover>
    </template>
    
    <script setup lang="ts">
    import { CloseBold, ArrowDownBold } from '@element-plus/icons-vue'
    import type { MenuItem } from '@/interface/menu'
    import { useMenuRouterStore } from '@/stores/menu-router'
    import { useTabsStore } from '@/stores/tabs'
    import { useAppStore } from '@/stores/app'
    const router = useRouter()
    const menuRouterStore = useMenuRouterStore()
    const tabsStore = useTabsStore()
    const appStore = useAppStore()
    // tabs功能操作
    const buttonRef = ref()
    const popoverRef = ref()
    const onClickOutside = () => {
      unref(popoverRef).popperRef?.delayHide?.()
    }
    const handleCommand = (command: string) => {
      if (command === 'refresh') {
        appStore.isLoading = true // 展示数据加载状态
        appStore.isRouterAlive = false // 设置为false,卸载dom
        setTimeout(() => { // 此处采用了定时器,并没有采用网上比较常见的nextTick
          appStore.isRouterAlive = true // 设置为true,重新挂载dom
          appStore.isLoading = false // 隐藏数据加载状态
        }, 500)
      } else if (command === 'closeOther') {
        tabsStore.closeOther()
      } else {
        tabsStore.closeLeftOrRight(command)
      }
    }
    // ……
    </script>
    
    <style lang="scss" scoped>
    …… CSS样式
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    往期内容已全部收录在专栏中:

    git专栏_WEB前端李志杰的博客-CSDN博客

    Flutter专栏_WEB前端李志杰的博客-CSDN博客

    Vue专栏_WEB前端李志杰的博客-CSDN博客

  • 相关阅读:
    在Go项目中二次封装Kafka客户端功能
    ElementUI增删改的实现及表单验证
    Android实现ViewPager适配器kotlin简单实现
    在 CentOS 8.2 上安装 MySQL C/C++ 客户端库 libmysqlclient.so
    时域卷积定理&频域卷积定理
    离散数学 --- 图论基础 --- 子图和补图,握手定理
    ajax异步传值以及后端接收参数的几种方式
    Python文件及目录操作(基本文件操作篇)
    Linux内核分析与应用6-系统调用
    MyBatis 面试题
  • 原文地址:https://blog.csdn.net/qq_16221009/article/details/125753427