侧边栏抽屉通过 emit 通知父组件关闭遮罩层,核心是子组件触发事件、父组件监听并统一控制显隐状态;推荐用 v-model 实现双向绑定,抽屉内遮罩层 @click 触发 update:modelvalue 事件,内容区需 @click.stop 防止冒泡,可选监听 esc 键关闭。

侧边栏抽屉通过 emit 通知父组件关闭遮罩层,核心是子组件触发事件、父组件监听并控制显隐状态。关键在于父子职责分明:抽屉只负责“我被点了关闭”,不直接操作遮罩层;遮罩层的显示/隐藏由父组件统一管理。
父组件:用 v-model 或显式 props + events 控制开关
推荐使用 v-model 语义化双向绑定(本质是 value prop + input 或 update:modelValue 事件),更简洁清晰:
- 父组件传入
:model-value="drawerVisible",监听@update:model-value="val => drawerVisible = val" - 或传统写法:
:visible="drawerVisible"+@close="drawerVisible = false" - 遮罩层(
<div class="mask" v-show="drawerVisible">)与抽屉共用同一响应式变量 <h3>抽屉组件:在遮罩层点击时 emit 关闭事件</h3> <p>抽屉内部的遮罩层(通常为全屏半透明 div)应绑定 <code>@click,并触发自定义事件:- 模板中写:
<div class="drawer-mask" false></div> - 若用传统方式:
<div class="drawer-mask"></div> - 注意:确保遮罩层 z-index 高于抽屉内容,且点击区域覆盖完整;避免内容区事件冒泡干扰
补充细节:阻止点击穿透与事件委托
如果抽屉内容区域点击也意外关闭,需阻止事件冒泡:
- 抽屉内容容器加
@click.stop,例如:<div class="drawer-content">... <li>遮罩层本身不需要 <code>.stop,它就是关闭触发源 - 不用
@click.self,因为遮罩层通常无子元素,且 self 对全屏 div 意义不大 - 在
onMounted中添加:document.addEventListener('keydown', handleEsc) const handleEsc = (e) => e.key === 'Escape' && $emit('update:modelValue', false)- 别忘了
onUnmounted中移除监听,避免内存泄漏
可选增强:支持 Esc 键关闭
提升体验,抽屉挂载后监听
keydown.escape: - 模板中写:











