现在越来越多的开源工具使得开发效率大大提高,让开发者从繁琐的样式编写等工作中抽离出来,专注于前端逻辑的编写,很多时候只需要找到不同的工具、零件,按照自己的业务需求拼装在一起就是一辆很棒的车。只是不同的工具,组件也好、插件也好,都是由不同的人员开发维护的,属于独立的项目,但当我们要造车的时候,拿过来的零配件可能就有些地方无法相互兼容,比如多了个凹槽,导致两个零件无法很好的组装,这就需要手动去抹平这些地方。
就在昨天,我就遇到了这样一个兼容性问题。
最近做的项目中使用到了element-ui组件和better-scroll滚动插件,这两个都是非常棒的工具。这个问题是element-ui的dialog和better-scroll相遇后的层级问题。
先看看dialog的实现方式:
遮罩层实在body里创建一个div,层级为2002,fixed定位实现;
dialog层则写在了组件里面,也是fixed定位,层级为动态的,但总是比遮罩层的高一级,保证不被遮罩挡住。
当给元素加上better-scroll滚动效果后:
可以看到,遮罩层的位置没变,定位方式也没变,dialog也一样,唯一不同的是整个组件被better-scroll初始化后,在父级上增加了style属性,l里面是为了实现滚动的css3属性:transform,transition等,但是遮罩层却跑到了dialog上面!
问题就出在transform上,当一个元素拥有transform属性的时候,其子元素的所有fixed样式都将被默认转换成position:absolute,也就是绝对定位,这就导致z-index的失效。在这里,处于transform内的元素定位由fixed转变为absolute,而处于body里的遮罩层则不受影响,依然是fixed定位,导致这两者的相对定位失效。看了网上的资料,transform导致fiexd失效是无解的。
试了很多种方法,css样式修改走不通,只能用js方式了。
既然是better-scroll的transform属性导致的,那就想办法在处理better-scroll。
在点击添加应用,出现弹框时,下层的滚动是不需要的,所以此时可以销毁掉scroll实例,将对应元素的style移除,关闭弹框的时候再初始化scroll实例。
需要注意的一点是,不能用style="来移除transform属性,因为在ie下无效!
触发销毁事件和实例化事件
父组件接收事件,执行销毁和实例化滚动组件,着样既能解决fixed层级问题,又能兼容ie浏览器。
补充:
后来发现element-ui里面有滚动组件,只是官网没有列出其api,如果只是滚动效果,没有更多的需求,用element-ui的组件是最好的,引用:
import {Scrollbar} from "element-ui",再注册一下就可以用了,在页面中使用:<el-scrollbar></el-scrollbar>即可。但要解决弹出层覆盖的问题还需要一个关键的设置,给对应的dialog组件设置modal-append-to-body为false,官网的解释是:Dialog 自身是否插入至 body 元素上。嵌套的 Dialog 必须指定该属性并赋值为 true。设置了这个属性后弹框和背景层就在并列的位置上了,fixed层级才能有效