本篇文章介绍了一个在开发中遇到的诡异的问题,排查问题过程颇为艰辛,不过最终结果还是值得的,因为巩固了一些基础知识和好的调试方法,它们是:

fixed定位的特点

样式优先级的判定

如何使用浏览器的DOM还原一闪即逝的错误效果

1. 问题说明

在猎萝卜-猎头端,测试提出这样一个bug(禅道编号12828):

在猎萝卜的 订单 - 我的职位 - 已接单 入口,点击右侧职位列表的任意职位,在弹出职位预览之前(图2),会先看到职位详情的底部串到左下角位置(图1)

图1 异常状态

图2 回到正常的状态

2. 调用过程

线框说明图1

线框说明图1

首先介绍下触发整个动作的逻辑,为了方便理解,借用上面的线框图来说明:

projectList.vue是职位列表,其中每个职位对应的条目封装成了order-project-item.vue,点击order-project-item.vue后,会触发事件全局的expandOrderPreview

order-project-preview.vue作为一个常驻在界面右侧的组件,默认是收起在屏幕右侧的,在侦听到了expandOrderPreview事件以后,会从右侧弹出

next-bar-affix.vue作为order-project-preview.vue底部的子组件,会一起出现和消失

3. 具体的代码逻辑

在下图中的逻辑代码,整理成如下描述:

order-project-item.vue触发点击事件expandOrderPreview,被order-project-preview.vue侦听到,然后进行如下处理:

第一步 emit showOrderPreview事件

父级app-frame.vue收到showOrderPreview事件,给引用的order-project-preview.vue添加一个.previewing的样式

.previewing会使order-project-preview.vue的宽度从0变到特定宽度从而在右侧展示

第二步 调用refresh方法

将loading设置为2,order-project-preview.vue中详情面板受到loading==0的v-if控制,因此会隐藏;loading组件发现loading>0因此会有加载效果

异步调用getProjectDetail和getOrders 这两个方法,直到结果返回,loading值会递减至0,详情才开始正常展示,加载效果才会去除

order-project-preview.vue侦听到弹出事件

app-frame.vue被order-project-preview.vue的emit触发进行previewing样式添加

order-project-preview.vue的refresh方法的逻辑

order-project-preview.vue的模板

4. 一些基础知识

解决问题之前,通过查看样式代码,我们巩固了一些基础知识。

如下是抽取出来的DOM结构和样式设置:

.order-project-preview {

position: fixed;

top: 0;

bottom:0;

right: 0;

width: 300px;

}

.next-bar-affix {

position: fixed;

bottom: 0;

}

.next-bar-affix .h-affix {

position: fixed;

height: 60px;

}

.order-project-preview进行position: fixed设置后,DOM的位置会相对视口固定,通过left, right, top, bottom来设置定位

在上述示例代码中,.order-project-preview宽度300px,高度撑满屏幕,底部栏 .next-bar-affix底部内容区的高度为30px

其中.next-bar-affix部分的代码是由heyui的affix组件生成的,一个有意思的启发是,在.h-affix中也添加了一个bottom:0的属性。可以尝试将该属性去除,会发现底部的内容区域会跑到最底部之下,变得不可见。

综上,可以从上述效果图推测的一个结论是:

如果一个子容器设置了fixed定位,它的父容器也是fixed,那么在不指定子容器的left, right, top, bottom时,子容器的边界会以父容的top left作为边界。进一步可以推断,在我们的问题中,必然是有什么因素使得作为父容器的.order-project-preview失去了作为子容器定位基准的条件**,从而跑到了视口的左下角。

5. 具体推测

做过的一些不靠谱的推测:一个DOM样式的变化 A->A+B 实际上是 A -> 无 -> A+B,即order-project-preview.vue增加 .previewing的过程中,容器样式到无的中间过程暂时使得next-bar-affix.vue丢失了left的基准,从而导致在中过程中串到了视口左下角。

this.$emit('showOrderPreview');

this.refresh();

基于上述推测,为了解决这个问题,考虑将上述两行代码对调:

先让refresh的逻辑去触发order-project-preview.vue的隐藏,自然也就隐藏了next-bar-affix.vue

再触发showOrderPreview事件来order-project-preview.vue的展开

等 refresh触发的异步调用结束以后,order-project-preview.vue中的具体内容才连同next-bar-affix.vue被展示出来

但结果不如预期的那样,猜想也许是refresh 成功隐藏next-bar-affix.vue之前,this.$emit('showOrderPreview');的逻辑引起的弹出生效了,于是添加了如下代码(事实上纯属没有依据的HardCode):

this.$emit('showOrderPreview');

this.$nextTick(() => {

this.refresh();

})

运行,没在出现如上所示的问题,似乎是解决了。

6. 问题又重现了

然后,提交代码后,测试同学告知,该问题又重现了,重现步骤姑且略过,这时候联想到之前排错的过程中,就猜想可能跟浏览器的渲染顺序有关系,然后把浏览器的工作原理的基础介绍翻阅了一遍,但并没有解答这个问题。

又想起团队的caoq同学分享过如何监听DOM上的属性变化。问题难点无非在于无法让浏览器在某个异常的时刻停下来,如果能停下来观测DOM的结构和样式,差不多就可以排查到问题根源。于是给order-project-preview.vue的根节点设置了attribute modification的断点(设置方法如下图所示):

image.png

这时候意外地发现在异常发生时,主界面order-proejct-preview.vue的内容已经加载出来了(但却没显示),即不存在next-bar-affix.vue 丢失默认的left基准的问题。

倒是发现了该容器上添加了一个 .h-loading-parent的样式,这个样式定位为 relative 。由此基本能确定了在heyui的loading组件的渲染中,会修改所在父容器order-project-preview.vue的样式,给它添加上.h-loading-parent。

因为 order-project-preview.vue 最外围默认的样式是 fixed, 被.h-loading-parent覆盖之后变成了 relative(它们具有相同的优先级,后出现的relative覆盖前出现的fixed),从而导致了next-bar-affix.vue的left基准丢失。我们只要把给弹出的面板order-project-preview.vue加上更高优先级的fixed定位即可。

//loaing组件提供 样式

.h-loading-parent {

position: relative;

}

// 自书写的样式

.order-project-preview-page {

// 两个class累积的优先级为2,大于.h-loading-parent的1:

&.previewing {

position: fixed;

}

}

7. 再深入一些

问题:断点过程已经渲染好的面板却看不到内容,只看到一个错位的底部栏

通过查看heyui的组件源码的样式可以发现:

heyui组件在loading完毕后,会设置500ms的timeout来清除.h-loading-parent的样式(参加下图1),即内容渲染出来了,但是样式500ms内还没去除,也就导致了relative引起的错位

relative的属性同样影响到了 .order-project-preview-page.previewing 的高度,因为它的各个子元素无一例外都absolute的,因此这样的文档流无高度的,而被覆盖的fixed,通过了 top',bottom`赋予了它和视口相同的高度。

Loading的渲染代码

问题2 我们在本地代码上无法重现该问题

在本地代码运行在浏览器的样式发现:.order-project-preview-page上设置的fixed的优先级高于 h-loading-parent的relative。

因此可以做一个猜测

在开发环境中库的样式被先加载,自己组件内地样式后加载,如果计算的优先级的值一样的话,自己组件的样式自然就失效了。

在线上环境,样式的代码经过压缩以后,并不能保留开发环境中的出现顺序,因此需要人为的设置来保证所期待的优先级。

postionfixed固定_position:fixed定位问题的解决相关推荐

  1. postionfixed固定_详解如何解决position:fixed固定定位偏移问题

    问题 css固定定位position:fixed很容易使用,就是相对浏览器的viewport进行定位,top:0;left:0就是在左上角. .container{ width: 100px; hei ...

  2. 固定布局(fixed layout)、流体布局(fluid layout)、弹性布局(elastic layout)、响应布局(responsive layout)理解和技巧归纳

    关于web页面布局,首先简单了解一下固定布局(fixed layout).流体布局(fluid layout).弹性布局(elastic layout).响应布局(responsive layout) ...

  3. 相对定位relative、绝对定位absolute、固定定位fixed

    注:默认情况下的定位是 postion:static: 使用定位时,常常使用偏移量对位置进行描述:left.right.top.bottom 定位时,使用z-indent可以元素的堆叠顺序,例:z-i ...

  4. 解决IE6下 position的fixed定位问题

    html{ _background:url(about:blank); /* 阻止IE6闪动 , 把空文件连接换成about:blank , 减少请求 */ } /* 图层 */ .pFixed{ p ...

  5. postionfixed固定_关于position:fixed的注意点

    position: fixed是CSS固定定位,一般用于导航栏吸顶效果.该属性使用的时候要注意一些细节: 1.固定定位的盒子必须有宽度 也就是必须设置width,如果没有设置宽度,那么该盒子的宽度就是 ...

  6. 前端系列——与众不同的移动端底部固定栏 fixed、absolute 兼容 iOS 和 Android 方案

    相信我,我分享的和你在其他博客上看到的终极方案是如此的与众不同! 做过移动端开发的同学,对底部DOM定位出现的各种奇葩情况已经深恶痛绝了吧,底部DOM设置不同的position,在Android和io ...

  7. 前端系列——与众不同的移动端底部固定栏 fixed、absolute 兼容 iOS 和 Android 方案...

    相信我,我分享的和你在其他博客上看到的终极方案是如此的与众不同! 做过移动端开发的同学,对底部DOM定位出现的各种奇葩情况已经深恶痛绝了吧,底部DOM设置不同的position,在Android和io ...

  8. 手机百度浏览器fixed定位问题

    如上边这样一张图片,底部有一个按钮 这个按钮固定在底部(fixed定位): 看似很简单的一个效果实现,然而在百度浏览器却出现了问题:这个底部固定定位按钮会闪现之后就不见了,其他浏览器上正常显示,找了挺 ...

  9. IE6下fixed失效的解决方法

    在网上找了好久,终于找到一种亲测有效的解决方法. <!--[if IE 6]> <script type="text/javascript"> (funct ...

最新文章

  1. 无法在终端中显示Git树
  2. Topaz Video Enhance AI中文版
  3. pyqt5 中QSS
  4. JMeter 正则表达式提取器(二)
  5. RSS接触 - RSS中的XML文档
  6. c从oracle到mysql移植_数据库从oracle移植到mysql时需要进行的修改
  7. POJ 1001 Exponentiation
  8. linux下查看内存频率,内核函数,cpu频率
  9. AutoCAD二次开发基础(二):曲线操作
  10. CSS网页布局中文排版的9则技巧
  11. N年前的实习记录 - 职场生涯应如何规划?
  12. Android 使用so库的遇到的坑
  13. 三个月通过信息系统项目管理师经验帖(2021年11月,新鲜出炉,高项详解)
  14. Python dic 方法汇总
  15. pytorch保存模型方法
  16. PHP工厂模式的好处
  17. 获取Device Name方法
  18. 前端的短信验证码如何做(和后端配合)
  19. php study计算闰年,IOS_IOS获取指定年月的当月天数,前言 在开发IOS中常常需要用 - phpStudy...
  20. 自然数的物理化学性质

热门文章

  1. 太干了!大俠『云飞杨』带你走进GFX!
  2. Win10笔记本电脑桌面容易卡死怎么办
  3. ExtraTrees原理
  4. TWaver2.5 Released!电信拓扑Web解决方案
  5. vb中rnd是什么意思
  6. Git学习————blibli大学
  7. 庞涓VS孙膑——一个很难的数学问题
  8. Travelling
  9. 浅析票据贴现、承兑和托收的区别和流程
  10. 采用外中断控制的LED彩灯设计