log
码中赤兔

[Vue3] 如何封装命令式组件

发布于 2024年12月9日
更新于 2025年1月6日
8 分钟阅读
Vue

在开发中,我们经常需要全局加载组件(如全屏加载提示)来展示操作状态。比如以下是一个简单的 FullscreenLoading.vue 组件:

<template>
  <div class="loading">
    <div class="spinner-border text-primary" role="status">Loading...</div>
  </div>
</template>

<style scoped>
.loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9999;
}
.loading .spinner-border {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.loading .spinner-border.text-primary {
  color: #ffffff;
}
</style>

一般情况下,我们可以通过在页面模板中使用组件,并用变量控制它的显示和隐藏:

<template>
  <FullscreenLoading v-if="showLoading" />
  <div class="wrapper">
    <button @click="clickHandler">Show Loading</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import FullscreenLoading from './components/FullscreenLoading.vue'

const showLoading = ref(false)

const clickHandler = () => {
  showLoading.value = true
  setTimeout(() => {
    showLoading.value = false
  }, 2000)
}
</script>

这种方法虽然直观,但如果多个页面需要相同的加载逻辑,就会出现大量重复代码,需要手动引入组件并维护变量状态。

为了解决这个问题,我们可以将加载逻辑封装成命令式组件,实现调用即显示,无需引入和维护额外变量。


封装命令式组件

通过 Vue 的createApp方法,我们可以动态创建组件实例,并将其挂载到 DOM 中:

import FullscreenLoading from '@/components/FullscreenLoading.vue'
import { createApp } from 'vue'

export function showLoading() {
  const app = createApp(FullscreenLoading)
  const container = document.createElement('div')

  app.mount(container)
  document.body.appendChild(container)

  return {
    close: () => {
      app.unmount()
      document.body.removeChild(container)
    },
  }
}

代码解析

  1. 动态创建组件实例:通过createApp方法生成FullscreenLoading的实例。
  2. 挂载到 DOM:创建一个 div 容器,将组件挂载到该容器中,并将容器追加到 body。
  3. 关闭函数:返回一个close方法,用于卸载组件并清理 DOM,避免内存泄漏。

使用封装的命令式组件

有了showLoading函数,显示全屏加载只需调用该方法,无需引入组件或维护状态:

<template>
  <div class="wrapper">
    <button @click="clickHandler">Show Loading</button>
  </div>
</template>

<script setup lang="ts">
import { showLoading } from './utils/loading.util'

const clickHandler = () => {
  const { close } = showLoading()
  
  setTimeout(() => {
    close()
  }, 2000)
}
</script>

调用showLoading时,加载组件会自动显示,并通过close方法手动关闭。这个实现简单明了,适用于多页面场景,也避免了重复性代码。


总结

通过封装命令式组件,我们可以用更简洁的方式实现全局加载等功能,带来更好的可维护性和开发效率。只需调用showLoading即可显示加载组件,关闭时调用返回的close方法。这样的封装不仅减少了页面模板的复杂度,还提升了组件的复用性,非常适合类似场景的动态 UI 操作。

希望这篇内容能帮到你!

关于

分享技术见解、经验和思考的个人博客

联系方式

  • Email: hushukang_blog@proton.me
  • GitHub

© 2025 码中赤兔. 版权所有