记一次蛋疼的前端调试(Antdv的popupover中有图片时第一次指示箭头错位问题)

248 阅读3分钟

使用的前端技术:vue2.x + antd1.7.8;其中出问题的组件:popupover组件.

问题描述:使用popupover组件的visible参数控制隐藏显示;popupover组件中使用了图片,鼠标移入后,会导致指示箭头偏离源头元素;第2+n次恢复正常

思考:鼠标移入目标元素后,目测图片有明显的加载过程(图片从上到下慢慢加载),此时指示箭头错位.问题原因就很明显了:

1.显示popupover弹窗的时候图片尚未加载,popupover组件内部文字内容高度计算出指示箭头的位置;

2.紧接着开始加载图片,图片加载结束后开始渲染图片,此时会撑高popupover弹窗,遗憾的是,popupover组件并没有监听高度变化这事件,导致弹窗变高,但指示箭头位置并没有跟着变.

处理方案(蛋疼蛋疼蛋疼):

知道了原因,解决就很简单了,在显示弹窗前,提前加载图片就完事.万万没想到这是我调试一下午的开端.

提前加载图片有很多种方式,最粗暴的方式就是在页面写个用样式隐藏的图片.如果图片较少可以用,但图片很多的话,会导致页面加载时间变长.

<img src="/shiba/yituge.png" style="display:none">

身为一个老前端肯定不会用这种方式,那就用js提前加载.

/** 预加载图片* */
export function preloadImg(url){
    return new Promise((resolve)=>{
        let img = document.createElement("img");
        img.onload = () =>{
          resolve(img);
        }    
        img.src=url;  
    });
}

//使用:
await preloadImg('/shiba/yituge.png');
this.控制popupover显示的变量 = true;

分分钟搞定,自信满满的测试.咦,还不好?代码有问题?不应该啊,反复测试修改后,难道是我promise+async+await用的不对?那就改成普通回调的方式逝世.

/** 预加载图片* */
export function preloadImg(url,cb){
    // 上面的方法体    let img = document.createElement("img");
    img.onload = () =>{  
        cb && cb(img)
    }
    img.src=url;}

这应该没问题了吧,然后又自信满满的测试,what a fake,还是老样子,(此时开始有点蛋疼了,蛋疼+1).

难道是浏览器出bug了?重启浏览器,前端疑难杂症终极解决方案,然并卵(蛋疼+10).

又经过一系列的修改测试,换浏览器测试,问题仍然存在.(蛋疼+100)

难道是我电脑有毒?让同事局域网内访问我的开发地址,她竟然没问题!!!(蛋疼+10086)

此时已经距发现问题已经过了2个多小时,我已经开始有点暴躁了.出去抽根烟冷静冷静,回想自己调试过程,突然想到一个细节.鼠标移入目标元素的时候,图片请求了2次

当时没在意,现在想想这是有问题的,明明只用js预加载了一次,但是出现2次请求,难道第二次是图片加载又请求了一次?再结合同事访问并没有出现问题,我顿悟了.丢下烟,回到办公桌看浏览器设置,果然如此.

开启这个配置后,本地开发就不会使用缓存文件.在我碰到的问题中鼠标移入js加载图片一次,显示弹层时候图片渲染渲染又重新加载了一次,就等于我的预加载工作白做了.

但从另一个角度想:没有哪个普通用户会打开浏览器控制台,并且开启这个开关,也就是说我的问题根本就不是问题,我只是自己把自己给坑了-_-.

不暴躁了,蛋也不疼了.继续愉快的代码.

问题复盘:

其实在调试过程中,也特意去观察过请求,看到2次图片请求,也没深入去想,只是感到有点奇怪.

SO:抽烟真的有助于写代码(并不是).