当前位置:首页 > VUE

vue3.0实现弹窗

2026-02-21 20:29:26VUE

使用 Vue 3.0 实现弹窗功能

基于 Teleport 和 Composition API 的弹窗组件

创建一个可复用的弹窗组件,利用 Vue 3 的 Teleport 将弹窗内容挂载到 body 下,避免样式污染。

<!-- Modal.vue -->
<template>
  <Teleport to="body">
    <div v-if="isOpen" class="modal-overlay" @click.self="close">
      <div class="modal-content">
        <slot></slot>
        <button @click="close">关闭</button>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
import { ref } from 'vue'

const props = defineProps({
  modelValue: Boolean
})

const emit = defineEmits(['update:modelValue'])

const isOpen = ref(false)

function open() {
  isOpen.value = true
}

function close() {
  isOpen.value = false
  emit('update:modelValue', false)
}

defineExpose({
  open,
  close
})
</script>

<style scoped>
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 8px;
  max-width: 80%;
}
</style>

在父组件中使用弹窗

通过 v-model 控制弹窗显示隐藏,也可以通过 ref 调用组件暴露的方法。

<!-- ParentComponent.vue -->
<template>
  <div>
    <button @click="showModal">打开弹窗</button>
    <Modal v-model="modalVisible">
      <h2>弹窗标题</h2>
      <p>这是弹窗内容</p>
    </Modal>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Modal from './Modal.vue'

const modalVisible = ref(false)
const modalRef = ref(null)

function showModal() {
  modalVisible.value = true
  // 或者直接调用组件方法
  // modalRef.value.open()
}
</script>

使用 provide/inject 实现全局弹窗控制

创建一个全局弹窗服务,方便在任何组件中调用。

// modalService.js
import { ref, provide, inject } from 'vue'

const ModalSymbol = Symbol()

export function provideModal() {
  const isOpen = ref(false)
  const content = ref(null)

  function open(component, props) {
    content.value = { component, props }
    isOpen.value = true
  }

  function close() {
    isOpen.value = false
  }

  provide(ModalSymbol, {
    isOpen,
    content,
    open,
    close
  })
}

export function useModal() {
  const modal = inject(ModalSymbol)
  if (!modal) throw new Error('Modal provider not found')
  return modal
}

全局弹窗组件实现

<!-- GlobalModal.vue -->
<template>
  <Teleport to="body">
    <div v-if="isOpen" class="modal-overlay" @click.self="close">
      <div class="modal-content">
        <component :is="content.component" v-bind="content.props" />
        <button @click="close">关闭</button>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
import { useModal } from './modalService'

const { isOpen, content, close } = useModal()
</script>

在应用中使用全局弹窗

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { provideModal } from './modalService'
import GlobalModal from './GlobalModal.vue'

const app = createApp(App)

app.component('GlobalModal', GlobalModal)
app.provideModal = provideModal

app.mount('#app')
<!-- SomeComponent.vue -->
<template>
  <button @click="showAlert">显示全局弹窗</button>
</template>

<script setup>
import { useModal } from './modalService'
import AlertComponent from './AlertComponent.vue'

const modal = useModal()

function showAlert() {
  modal.open(AlertComponent, {
    message: '这是一个全局弹窗!'
  })
}
</script>

弹窗动画效果

为弹窗添加过渡动画,提升用户体验。

<template>
  <Teleport to="body">
    <Transition name="modal">
      <div v-if="isOpen" class="modal-overlay" @click.self="close">
        <div class="modal-content">
          <slot></slot>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
.modal-enter-active,
.modal-leave-active {
  transition: opacity 0.3s ease;
}

.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

.modal-content {
  transition: transform 0.3s ease;
}

.modal-enter-active .modal-content {
  transition: all 0.3s ease;
}

.modal-enter-from .modal-content,
.modal-leave-to .modal-content {
  transform: scale(0.9);
}
</style>

这些方法涵盖了 Vue 3 中实现弹窗的主要技术方案,可以根据项目需求选择适合的方式。

vue3.0实现弹窗

分享给朋友:

相关文章

vue实现导航切换内容

vue实现导航切换内容

Vue实现导航切换内容的方法 在Vue中实现导航切换内容,可以通过以下方式实现: 使用动态组件 动态组件通过<component :is="currentComponent">实现内容…

vue实现导航栏切图

vue实现导航栏切图

Vue 实现导航栏切图 使用 Vue Router 实现基础导航 在 Vue 项目中,可以通过 Vue Router 实现导航栏的路由切换。创建一个导航栏组件,并在其中使用 <router-li…

vue实现字母添加排序

vue实现字母添加排序

实现字母添加排序的方法 在Vue中实现字母添加排序功能,可以通过以下步骤完成: 创建Vue实例并定义数据 new Vue({ el: '#app', data: { lette…

vue实现文章锚点定位

vue实现文章锚点定位

实现文章锚点定位的方法 在Vue中实现文章锚点定位可以通过多种方式完成,以下是几种常见的方法: 使用原生HTML锚点 通过HTML的id属性和<a>标签的href属性实现锚点跳转。在Vu…

vue实现通知

vue实现通知

Vue 实现通知功能的方法 使用 Vue 实现通知功能可以通过多种方式实现,以下是一些常见的方法: 使用 Vue 的全局事件总线 在 Vue 中可以通过事件总线实现通知功能。创建一个全局事件总线,然…

vue实现token

vue实现token

Vue 中实现 Token 认证的方法 在 Vue 中实现 Token 认证通常涉及前端与后端的交互,包括 Token 的获取、存储、发送和刷新等操作。以下是具体实现步骤: 获取 Token 用户登…