对于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>

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐