组合式 API 封装模态框逻辑的核心是抽离打开、关闭、状态管理与事件通知为独立的 composition function,如 useModal,返回 isOpen、open、close、toggle 等响应式状态与控制函数,支持 Esc 关闭、v-model 同步、Teleport 挂载及无障碍访问。

用组合式 API 封装可复用的模态框逻辑
核心思路是把“打开、关闭、状态管理、事件通知”这些通用行为抽离成独立的 composition function,不依赖具体组件结构,只暴露控制函数和响应式状态。这样任何组件都能直接 import 并使用,避免重复写 ref(false)、emit('close') 这类代码。
定义 useModal 逻辑函数
创建 composables/useModal.js(或 .ts):
import { ref, onBeforeUnmount } from 'vue'
export function useModal() {
const isOpen = ref(false)
const open = () => { isOpen.value = true }
const close = () => { isOpen.value = false }
const toggle = () => { isOpen.value = !isOpen.value }
// 自动处理 Esc 键关闭
const handleKeydown = (e) => {
if (e.key === 'Escape' && isOpen.value) close()
}
onBeforeUnmount(() => {
document.removeEventListener('keydown', handleKeydown)
})
document.addEventListener('keydown', handleKeydown)
return { isOpen, open, close, toggle }
}
在模态框组件中使用
在 Modal.vue 的 <script setup></script> 中直接调用:
<script setup></script>
import { defineEmits, defineProps } from 'vue'
import { useModal } from '@/composables/useModal'
const props = defineProps({ title: String })
从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。
const emit = defineEmits(['update:modelValue', 'close'])
// 复用逻辑
const { isOpen, open, close, toggle } = useModal()
// 同步父组件 v-model
isOpen.value = props.modelValue
const updateModel = (val) => {
emit('update:modelValue', val)
if (!val) emit('close')
}
// 监听 isOpen 变化,同步到父组件
watch(isOpen, updateModel)
在业务组件中调用更简洁
父组件不再需要手动维护布尔值,只需绑定 v-model 即可:
这里是自定义内容
<script setup></script>
import Modal from '@/components/Modal.vue'
import { ref } from 'vue'
const showDialog = ref(false)
进阶:支持 Teleport 和焦点管理
若需挂载到 或处理键盘焦点,可在 useModal 中增强:
- 返回一个
triggerRef,用于在 Teleport 内部触发渲染 - 添加
focusFirstElement()方法,在打开时自动聚焦标题或第一个可交互元素 - 集成
aria-modal="true"和aria-hidden切换,提升无障碍体验
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










