解决 element-ui 抽屉弹窗、弹窗、气泡弹窗、消息弹窗、确认弹窗【el-drawer、el-dialog、el-popover、$message、$confirm】的 遮罩层z-index问题
解决 element-ui 抽屉弹窗、弹窗、气泡弹窗、确认弹窗【el-drawer、el-dialog、el-popover、$confirm】的 遮罩层z-index问题
对于this.$confirm 通过customClass传一个z-index样式名 是控制的 确认弹窗里内容dom的层级,如果需要设置整个确认弹窗的z-index,可以通过zIndex传入【element-ui文档里没有查到,但是在源码里找到了一个zIndex prop】。
在抽屉弹窗<el-drawer>上要弹出弹窗<el-dialog>,弹窗里面还有<el-popover>,抽屉弹窗js里还有this.$confirm(),弹窗层级顺序全部要正确,可以通过组合传class、customClass、zIndex来保障第一次打开抽屉后的所有弹出层的层级顺序是正确的,但是element-ui组件里的弹出层用到了node_modules\element-ui\lib\utils\popup\popup-manager.js,而该文件对应的导出对象PopupManager内部维护了一个zIndex属性,这个zIndex属性会不断累加,因此给一些弹窗组件设置了 z-index:9000 !important;这样的样式后,第一次打开抽屉弹窗及里面的所有弹窗时,element-ui生成的遮罩层dom【同时打开的所有element-ui弹窗公用同一个遮罩层dom,可在浏览器控制台的查看元素界面里的”</body>“前看到一个”<div class="v-modal" style="z-index: 2002;" tabindex="0"></div>“这样的dom节点】的z-index值比较低【例如2002】,但会在新打开的弹窗的z-index基础上不断累加【
node_modules\element-ui\lib\utils\popup\popup-manager.js里有如下方法:
nextZIndex: function nextZIndex() {
return PopupManager.zIndex++;
},
例如加载了一个设置了z-index:9000 !important;的弹窗后,PopupManager.zIndex会直接在9000的基础上开始累加。
】,这就会导致关闭抽屉弹窗,乃至销毁抽屉弹窗后,再次打开抽屉弹窗时,element-ui生成的遮罩层dom的z-index已经比所有抽屉弹窗内弹窗样式里固定指定的z-index值还要高,就会导致用户操作不了抽屉弹窗及其子弹窗里的内容,因为整个屏幕都被一个z-index值很高的遮罩层盖住了。所以一个有效的解决办法就是通过v-if控制最外层抽屉弹窗的加载,并在其created()生命周期里记录下PopupManager.zIndex,然后在其beforeDestroy()生命周期里将记录下的打开抽屉弹窗前的PopupManager.zIndex 赋值给 PopupManager.zIndex,然后再打开抽屉弹窗,这时element-ui生成的遮罩层dom的z-index属性值就会跟第一次打开抽屉弹窗时的z-index值一样了,问题解决。
示例代码(代码缩减版,重点看prevZIndex):
// 全局样式
.z-9000{z-index:9000 !important;}
.z-9001{z-index:9001 !important;}
.z-9002{z-index:9002 !important;}
.position-relative{position: relative}
// index.vue
<drawer v-if="drawerShow"></drawer>
// drawer.vue
</template>
<el-drawer class="z-9000">
<dialog v-show="dialogShow"></dialog>
</template>
<script>
import {PopupManager} from 'element-ui/lib/utils/popup'
export default {
data() {
return {
prevZIndex:'',
}
},
created() {
this.prevZIndex = PopupManager.zIndex;
},
beforeDestroy(){
PopupManager.zIndex = this.prevZIndex;
},
methods:{
submit() {
this.$confirm("确认。", "提示", {
zIndex:9002,
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
// customClass: "position-relative z-9002"
})
.then(() => {
this.$message.success({
message:'成功',
customClass: "z-9002"
})
})
}
},
}
</script>
// dialog.vue
<el-dialog
class="z-9001"
>
<el-form-item>
<template slot="label">
<span>
<el-popover
:append-to-body="true"
popper-class="z-9002"
>
</el-popover>
</span>
</template>
<el-select
popper-class="z-9002"
>
</el-select>
</el-form-item>
</el-dialog>
在此基础之上,如果遇到组合更复杂的情况,可以通过拆分出单元,在每个单元里及时清理掉 弹窗层级累加的副作用来解决。
// childComponent.vue
<template>
<div>
<el-dialog class="z-9002" v-if="dialogShow" @close="dialogShow=false;resetPopupZIndex();" @submit="doSubmit"></el-dialog>
</div>
</template>
<script>
import { PopupManager } from "element-ui/lib/utils/popup";
export default({
data() {
return {
dialogShow:false,
prevZIndex: "", // 弹出层之前的"v-model" div 的 z-index。
}
},
mounted() {
this.prevZIndex = PopupManager.zIndex;
},
methods: {
// 重置弹窗层级,以清理掉 弹窗层级 累加的 副作用。
resetPopupZIndex(){
PopupManager.zIndex = this.prevZIndex;
},
testFun(){
this.$alert("提示内容文本", "提示", {
zIndex:9002,
confirmButtonText: "确定",
}).finally(()=>{
this.resetPopupZIndex();
});
},
doSubmit(data){
this.resetPopupZIndex();
this.testFun();
}
}
}
</script>
更多推荐
所有评论(0)