前言
今年十月份,我曾發布一篇文章《Chrome53 最新版驚現無厘頭卡死 BUG!》,不過那個BUG在最新的 Chrome 54 中已經修正。
而今天即將發布的Chrome弱智BUG:
- 僅 Chrome 53 - Chrome 55(2016-12-05發布的)中存在問題
- 國內雙核瀏覽器 Chrome 45 中沒有問題
- Firefox,Edge,IE11-IE8瀏覽器中都沒有問題
發現問題
最近在和客戶溝通中,發現一個奇怪問題:
1. 頁面中存在一個選項卡控件,選項卡里面是IFrame,頁面初始顯示時有縱向滾動條出現
2. 來回切換選項卡一次,原來選項卡頁面的滾動條居然消失了!!
3. 奇怪的時,此時在選項卡頁面內滑動鼠標滾輪,還是能夠上下滾動頁面的
頁面打開時的樣子:
來回切換一次選項卡后的樣子:
奇怪的是,此時鼠標滾動還能上下滾動頁面:
當然首先懷疑的就是自己寫的代碼問題,但是查了一遍居然毫無頭緒。在此期間我們還發現如下問題:
1. FineUIPro從最新版v3.3,到之前v3.2,v3.1,v3.0.... 無一例外都有這個問題。這就有點不可思議了,我們開源版有 1300 多位捐贈用戶,專業版有 100 多個企業客戶,如此明顯的一個BUG不可能這么多版本都沒有被發現!!
假設之前的版本根本就沒有這個問題,那么就是瀏覽器版本升級引入的BUG了。
2. 在Firefox,Edge,IE11,IE10,IE9,IE8下測試都沒有這個問題,只有Chrome下才出現問題!!
由於,我們不得不懷疑是新版 Chrome 引入的BUG,為了驗證這個想法,我們需要一個非常簡單的可重現例子。
驗證問題
由於FineUIPro本身的客戶端代碼還是很復雜了,為了避免其他代碼的影響,我們需要一個可重現的簡單的例子:
頁面一:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> <input type="button" value="頁面二" onclick="document.getElementById('frame1').style.display = 'block'; document.getElementById('frame2').style.display = 'none';" /> <input type="button" value="頁面三" onclick="document.getElementById('frame1').style.display = 'none'; document.getElementById('frame2').style.display = 'block';" /> <div style="border:solid 1px red;width:400px;height:200px;"> <iframe id="frame1" style="width:100%;height:100%;border:none;" src="./page2.html"></iframe> <iframe id="frame2" style="width:100%;height:100%;border:none;display:none;" src="./page3.html"></iframe> </div> </body> </html>
這個頁面代碼非常簡單,兩個按鈕,兩個IFrame,默認顯示第一個IFrame,通過按鈕來切換兩個IFrame的顯示。
頁面二:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> page2 </body> </html>
頁面三:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> page3 <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> page3 </body> </html>
下面分別在不同瀏覽器下運行效果:
Chrome 55.0.2883.75
FireFox 50.0.2
Edge
IE11
毫無疑問,這個是Chrome的BUG,那么到底是從哪個版本開始才出現的呢,這個就不好追蹤。
我們也沒有那么多精力把每個Chrome版本都測試下,所以就安裝了兩款國內的雙核瀏覽器,分別用Chrome內核測試:
第一款產品是 360安全瀏覽器,極速模式下 Chrome 版本是 45,比較老,正好用來測試:
哈哈,看來 Chrome v45 還沒有這個BUG,這就好辦,說明這個BUG是Chrome新版才引入的!!
第二款產品是 QQ 瀏覽器,Chrome內核是 53
看來 Chrome 53 版本已經引入了這個BUG。
所以我們可以大致把引入這個BUG的Chrome版本限定在 v53 - v55(這個是2016-12-05 才發布的)。
解決問題
既然那么多Chrome版本都存在這個問題,要么是Google開發人員沒發現,要么是不想修正了。
這里也順便吐槽一下Chrome:雖然Chrome的運行速度最快,開發工具也非常方便,但是長期堅持在JavaScript編碼第一線,居然發現了好多個僅在Chrome下出現的問題,讓人恍惚有點IE6的感覺。僅僅是在 FineUIPro 就有好幾處是 Chrome Only 的代碼,有空我會再分享幾個出來。
不管Google怎么辦,這個問題還是要解決,又要是 Chrome Only 的代碼了,哎!
1. 首先懷疑是 iframe 的 width:100% 和 height:100% 搞的鬼
由於代碼結構太簡單,沒有多少讓人懷疑的地方,就先把這個寬度和高度改為固定值試下:
頁面四:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> <input type="button" value="頁面二" onclick="document.getElementById('frame1').style.display = 'block'; document.getElementById('frame2').style.display = 'none';" /> <input type="button" value="頁面三" onclick="document.getElementById('frame1').style.display = 'none'; document.getElementById('frame2').style.display = 'block';" /> <div style="border:solid 1px red;width:400px;height:200px;"> <iframe id="frame1" style="width:400px;height:200px;border:none;" src="./page2.html"></iframe> <iframe id="frame2" style="width:400px;height:200px;border:none;display:none;" src="./page3.html"></iframe> </div> </body> </html>
運行一下,問題依舊!
這時如果用Chrome調試工具查看,發現滾動條的位置還在,只是不顯示:
2. 之前遇到類似的問題,我們可以強制瀏覽器重新渲染
網絡上早已有相應的解決版本:查看StackOverflow上相關的技術帖子
頁面五:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> <script> function fixSize() { var container1 = document.getElementById('container1'); container1.style.overflow = 'hidden'; container1.scrollWidth; container1.style.overflow = 'auto'; } </script> <input type="button" value="頁面二" onclick="document.getElementById('frame1').style.display = 'block'; document.getElementById('frame2').style.display = 'none'; fixSize();" /> <input type="button" value="頁面三" onclick="document.getElementById('frame1').style.display = 'none'; document.getElementById('frame2').style.display = 'block'; fixSize();" /> <div style="border:solid 1px red;width:400px;height:200px;" id="container1"> <iframe id="frame1" style="width:400px;height:200px;border:none;" src="./page2.html"></iframe> <iframe id="frame2" style="width:400px;height:200px;border:none;display:none;" src="./page3.html"></iframe> </div> </body> </html>
運行,問題依舊!
怪了,這個強制Chrome重新渲染的代碼之前驗證過的,這次居然也不行了。
郁悶中。。。。。先出去散步。。。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
散步中。。。。
3. 散步回來,覺得還是應該從強制Chrome渲染入手,這次我們來改變高度
頁面六:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> <script> function fixSize() { var container1 = document.getElementById('container1'); container1.style.height = '199px'; container1.scrollWidth; container1.style.height = '200px'; } </script> <input type="button" value="頁面二" onclick="document.getElementById('frame1').style.display = 'block'; document.getElementById('frame2').style.display = 'none'; fixSize();" /> <input type="button" value="頁面三" onclick="document.getElementById('frame1').style.display = 'none'; document.getElementById('frame2').style.display = 'block'; fixSize();" /> <div style="border:solid 1px red;width:400px;height:200px;" id="container1"> <iframe id="frame1" style="width:100%;height:100%;border:none;" src="./page2.html"></iframe> <iframe id="frame2" style="width:100%;height:100%;border:none;display:none;" src="./page3.html"></iframe> </div> </body> </html>
帥呆了,這次居然可以了!!!現在Chrome 55下能正常運行了。
4. 優化一下,可以改變iframe的高度,而不是外部容器的高度,這樣就不用硬編碼了,代碼更通用
頁面七:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> </title> </head> <body> <script> function fixSize(iframeId) { var iframe = document.getElementById(iframeId); iframe.style.height = '99%'; iframe.scrollWidth; iframe.style.height = '100%'; } </script> <input type="button" value="頁面二" onclick="document.getElementById('frame1').style.display = 'block'; document.getElementById('frame2').style.display = 'none'; fixSize('frame1');" /> <input type="button" value="頁面三" onclick="document.getElementById('frame1').style.display = 'none'; document.getElementById('frame2').style.display = 'block'; fixSize('frame2');" /> <div style="border:solid 1px red;width:400px;height:200px;" id="container1"> <iframe id="frame1" style="width:100%;height:100%;border:none;" src="./page2.html"></iframe> <iframe id="frame2" style="width:100%;height:100%;border:none;display:none;" src="./page3.html"></iframe> </div> </body> </html>
這樣也行,也算是解決了這個Chrome Only的BUG!!
后記
每次給老婆說起這樣的稀奇古怪事,老婆都會嘲笑我是代碼泥瓦匠,只能從外部修修補補。不過能修補上也算是阿彌陀佛了。
誰讓咱一直堅持在代碼一線呢。
在線演示
頁面一(原始頁面,Chrome下存在BUG):http://fineui.com/demo_pro/chromebug1/page1.html
頁面四(仍然有問題):http://fineui.com/demo_pro/chromebug1/page4.html
頁面五(仍然有問題):http://fineui.com/demo_pro/chromebug1/page5.html
頁面六(修正了Chrome下的問題):http://fineui.com/demo_pro/chromebug1/page6.html
頁面七(修正了Chrome下的問題):http://fineui.com/demo_pro/chromebug1/page7.html