第3节:el-select 弹窗定位、滚动穿透与挂载容器(popper-append-to-body /teleported)
适用 Vue3 + Element Plus,Element Plus 中旧
popper-append-to-body已替换为teleported
知识点说明
teleported:控制下拉弹窗 DOM 挂载位置teleported="true"(默认):弹窗 DOM 会被挂载到body标签下,脱离当前组件 DOM 层级。
✅ 优点:不会被父容器overflow:hidden、z-index遮挡,大部分场景推荐。
❌ 缺点:弹窗不在组件内部,样式穿透、事件冒泡会有差异。teleported="false":弹窗 DOM 留在组件自身 DOM 内。
✅ 优点:DOM 结构在一起,scoped 样式更容易控制。
❌ 缺点:父容器如果设置overflow: hidden,下拉会被截断!
popper-offset:弹窗和选择框之间的偏移距离,单位 pxplacement:弹窗弹出方位,可选:bottom-start(默认) /bottom/top-start/top
完整测试代码
<template>
<div class="container">
<p>teleported=true(默认,挂载body)</p>
<el-select
v-model="value1"
placeholder="请选择"
popper-offset="8"
placement="bottom-start"
>
<el-option label="选项1" value="1" />
<el-option label="选项2" value="2" />
<el-option label="选项3" value="3" />
</el-select>
<div style="margin-top: 30px; overflow: hidden; height: 60px;">
<p>teleported=false,父容器overflow:hidden(会截断弹窗!)</p>
<el-select
v-model="value2"
placeholder="请选择"
:teleported="false"
popper-offset="8"
placement="bottom-start"
>
<el-option label="A" value="A" />
<el-option label="B" value="B" />
<el-option label="C" value="C" />
</el-select>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const value1 = ref('')
const value2 = ref('')
</script>
<style scoped>
.container {
padding: 20px;
}
</style>
测试要点
- 打开第一个下拉,弹窗正常弹出,不会被容器限制。
- 打开第二个下拉,会发现下拉弹窗被父容器截断 ,这就是
teleported=false的典型坑。 - 修改
placement="top",弹窗会向上弹出;修改popper-offset="15",弹窗离输入框距离变大。
常见业务坑:弹窗被父盒子遮挡,优先检查 teleported 和父元素 overflow 属性。
