关于element-ui组件的弹窗层级问题

1,495 阅读3分钟

关于element-ui组件的弹窗层级问题

关于element-ui组件的层级问题

拥有定位的元素的层级高低由z-index决定,那么element里是怎么设置或者初始化这个值的呢

4c1db456abbb46a970618288750a9fe2166716 (1).png

初始化:

1、如果已经初始化过,则使用本地的z-index
2、未初始化则使用Vue.prototype.$ELEMENT中的z-index属性,这个值是什么呢,见下图,是我们在use的时候传递的参数。

96effc29459dc24a2597c1a0faf07bfe325581.png 3、如果没有初始化,也没有传入值,则默认值为2000

值的变化:

初始化完成之后,在我们使用poper类型的组件的过程中,每次关闭后打开,z-index的值会自增一次,并且这个自增后的值是所有poper类组件共用的。

可以看到第一次我们打开日期弹窗z-index的值是2001,因为初始值是2000,打开后自增了1。

这是第二次打开,为什么变成2003了呢,这是因为我们之前说过,弹窗组件的z-index的自增后的值是共享的,我们先打开了dialog,值变为2002,再打开日期弹窗,就变成了2003了。(图之后补)

那么它具体是怎么做的呢

0373bf7de8c29bf240769271585b0fa285398.png

我们可以看到首先对visible进行监听,在为true的时候调了open方法

b568382f5429f37d646446b23bb9edb9183920.png

open方法里对延迟做了个判断,接着调用了doOpen,在其内部调用了nextZIndex,对z-index进行了自增

cdd43e50f8bc2e49e3003a1b84bb4685201477.png

22e52da2124f0f5b66f5101b95a91d0d56433.png

错误来源

看到这里好像没什么问题,既然每个弹窗点击后都会自增,那么理论上应该不会出现遮挡。因为当前点击的弹窗永远比其他弹窗z-index大1。可惜可惜,世界上的事要是都这么简单就好了。

代码若只如初见,何事秋风悲画扇。

截屏2024-01-18 下午3.24.26.png点进去

截屏2024-01-18 下午3.30.42.png

截屏2024-01-18 下午3.37.02.png 会发现popupManager对象被导入,而我们对z-index的操作都定义在这个对象上。因为导出的popupManager对象是引用类型,所以组件间共享这个z-index变量,问题就出在这。因为封装的工程组件element的来源和el-dialog这类不同,或者说有可能不是用的element而是另外的组件库,导致他们使用了不同的实例对象,各自的popupmanager不同。比如点击了封装的组件,它的z-index加1,el-dialog的z-index并不会发生变化。但是我点击了el-date-picker,el-dialog的z-index也会同步变化,因为它两操作的是同一个实例对象。

解决方案

1、给dialog,drawer这样的弹窗设置z-index值为2000,保证它们每次打开都被初始化为初始值。这样之内的弹窗不管如何点击都不会被遮挡。缺点:过于繁琐,每个组件都需要加
2、手动在Vue.use的时候设置一个值,比如20000这样远远大过各个工程组件默认值的数字。缺点:如果弹窗真的使用了这么多次,仍然会出现问题。
3、组件库监听使用工程的z-index属性,在发生变化的时候同步设置一下值。缺点:需要加额外的逻辑,容易导致其他的bug出现。

未完待续。。。