考察点分析

本题主要考察以下核心能力维度:

  1. 组合式API应用能力:考察对Vue3组合式API的逻辑封装能力,能否将状态管理与逻辑复用有机结合
  2. Portal机制理解:验证对Teleport特性的理解深度,能否正确实现跨DOM层级渲染
  3. 交互设计完整性:检测键盘事件与点击事件处理的完备性,包括事件委托与冒泡控制

技术评估点包括:

  • 响应式状态管理(ref/reactive)
  • Teleport的DOM挂载机制
  • 事件监听的生命周期管理
  • 可复用组件的接口设计

技术解析

关键知识点

  1. Composition API逻辑封装 > Teleport实现机制 > 事件委托处理
  2. 模态框状态通过ref驱动,封装为独立可复用模块
  3. Teleport解决z-index层级战争问题,确保模态框脱离父级上下文
  4. 通过事件源判断实现精准的遮罩层点击检测
  5. 通过键盘事件监听实现ESC关闭,注意多实例竞争条件

原理剖析

组合式API通过setup()函数将状态逻辑打包为独立单元,使用provide/inject实现跨组件状态共享。Teleport组件通过to属性指定目标容器,解决模态框受父容器overflow:hidden样式限制的问题。

事件处理需注意:遮罩层点击事件需校验event.target是否为遮罩层本体,防止内容区域点击误触发。ESC监听需在组件挂载时注册全局事件,并在卸载时及时销毁,避免内存泄漏。

常见误区

  • 直接使用事件冒泡处理遮罩层点击,导致内容区域误触发
  • 忘记移除全局事件监听导致多实例干扰
  • 未处理多个模态框同时存在时的ESC关闭优先级

问题解答

使用组合式API封装模态框状态逻辑的核心是创建响应式状态容器。通过useModal函数导出isOpen状态和操作方法,Teleport组件确保模态框渲染到body末端。遮罩层点击关闭通过校验事件目标实现,ESC关闭使用document.addEventListener注册全局监听。

关键技术实现:

  1. 使用ref创建响应式状态
  2. Teleport指定to="body"实现跨DOM层级渲染
  3. 通过event.target === modalRef.value精准判断遮罩层点击
  4. onMounted生命周期注册/移除事件监听

解决方案

编码示例

  // 组合式逻辑封装
const useModal = () => {
  const isOpen = ref(false)
  
  const open = () => (isOpen.value = true)
  const close = () => (isOpen.value = false)

  return { isOpen, open, close }
}

// 模态框组件
<template>
  <teleport to="body">
    <div v-if="isOpen" class="modal-mask" @click="handleMaskClick">
      <div class="modal-content" ref="modalContent">
        <slot />
        <button @click="close">关闭</button>
      </div>
    </div>
  </teleport>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'

const props = defineProps({
  // 支持自定义关闭策略
  closeOnEsc: { type: Boolean, default: true }
})

const { isOpen, close } = useModal()
const modalContent = ref(null)

const handleMaskClick = (event) => {
  // 精准点击检测
  if (event.target === modalContent.value.parentElement) {
    close()
  }
}

// ESC关闭逻辑
const handleKeydown = (e) => {
  if (e.key === 'Escape' && props.closeOnEsc) {
    close()
  }
}

onMounted(() => {
  document.addEventListener('keydown', handleKeydown)
})

onBeforeUnmount(() => {
  document.removeEventListener('keydown', handleKeydown)
})
</script>
  

可扩展性建议

  1. 性能优化:使用CSS transform代替top/left定位提升动画性能
  2. 多实例支持:通过事件优先级队列管理多个模态框的ESC关闭顺序
  3. 无障碍支持:添加role=“dialog"和aria-modal属性
  4. 低端设备适配:增加触摸事件支持,优化移动端点击体验

深度追问

  1. 如何防止模态框内容被父组件CSS样式干扰? 提示:Teleport的DOM脱离+CSS作用域控制

  2. 多层级模态框场景下如何管理z-index? 提示:动态栈管理+上下文注入

  3. 如何实现关闭动画与状态同步? 提示:transition组件+Promise异步处理

Last updated 06 Mar 2025, 13:07 +0800 . history