[前端] 記錄工作中遇到的各種問題(Bug,總結,記錄)


最近一年,在開發實踐過程中遇到了不少問題,大多都能得到解決

部分知其原理,部分只能做到解決問題,而半年前遇到的問題,或多或少都忘得差不多了

是該記錄一下一些問題,防止再遇到就得再查資料了

 

1. 瀏覽器在開啟有道划詞插件的時候,使用 AjaxFileUpload 插件上傳文件報錯

開啟插件時,該插件會往文檔中添加音頻元素節點

而AjaxFileUpload插件的上傳文件處理方式是,獲取返回的實體內容,直接進行eval 解析,解析失敗,報錯,則無法上傳

這插件在舊系統中常用到,解決辦法就是不用這個插件,或者停用有道划詞插件

另外,我的解決方案則是用了FormData對象來異步上傳文件

 

2. Uncaught TypeError: jQuery.handleError is not a function

使用某些舊插件的時候,會出現這個錯誤

插件使用了handleError這個方法,而新版的jQuery以及去除了這個方法,所以這時可以棄用插件或者為JQ加回此方法

jQuery.extend({

    handleError: jQuery.handleError || function( s, xhr, status, e ) {
        // If a local callback was specified, fire it
        if ( s.error ) {
            s.error( xhr, status, e );
        }
        // If we have some XML response text (e.g. from an AJAX call) then log it in the console
        else if(xhr.responseText) {
            console.log(xhr.responseText);
        }
    }

});

 

3. 異步方式實現導出Excel表格

用異步的方式導出數據,用Ajax貌似不行

目前想到的方法就是用iframe,設置不同的src即可讓后端返回相應數據

另外,剛發現的一個異步導出文件的方式是,直接設置當前URL為接口的路徑即可

window.location.href = '?p.......';

 

 

4. 頁面使用Angular.js(1),頁面中iframe中初始設置src屬性的話,會導致頁面重新加載一次

例如設置一個初始值,某些操作之后再更改src

<iframe src="#" class="export-iframe"></iframe>

Controller似乎會觸發兩次,可以看到加載的請求多觸發了一次,且第二次的鏈接中會多了一個#

解決辦法就是直接不設置這個屬性

<iframe class="export-iframe"></iframe>

 

5. 父頁面中有iframe,iframe里面有分頁按鈕,在父頁面對iframe做加載之后監聽iframe中點擊事件的操作,初始第一頁正常,但點擊第二頁之后事件就失效了

原代碼:

第一次成功打印出來,即觸發了load事件,但點擊下一頁后,iframe實際上已經刷新了,但並不會再觸發這個load事件

后來的解決辦法是換了種監聽方法,區別主要是獲取iframe對象的方式變了,還不知為啥會這樣?

 

6. 在iframe中的預覽pdf文件時,有時embed元素未占滿整個iframe,而是正好一半,一半

目前還不知如何解決,把embed的寬高由100%設置成接近99%的時候,反而占滿iframe的概率增多了不少..

 

7. 在iPad下,無法實現自動聚焦

這問題應該是解決不了的,是iOS自帶的,方案只能是由用戶觸發mousedownmouseupclick之類的事件后再調用

 

8. 有個插件叫做 magicsearch ,初期用得還好,不過之后斷斷續續發現了一些問題

在匹配不到數據的時候,匹配結果直接顯示了error文案,看看源碼,直接改掉

第二個坑是它直接把綁定元素的事件都注銷了,這樣太暴力很不好

第三個坑是它給只讀的style屬性賦值,這種方式在嚴格模式是被禁止的,而這插件正好自個又用了嚴格模式

坑就坑在:在Angular.JS(1)環境下使用iPad的時候才報錯,PC上用Angular.JS正常,iPad下用非Angular.js正常..

解決方法也很暴力,直接去掉插件的嚴格模式

第四個坑是它用了Array.from,而這方法支持度是chrome45+,所以稍低版本的就遭殃了

第五個坑就是它監聽輸入事件只用里keyup,應該還要考慮input與change事件

 

9. bootstrap v3 的collapse折疊組件使用了click的事件監聽方式,在移動端會有300ms的延遲

官方貌似在v4中修復了,用v3的話,就自個添加touchstart事件的支持,還要注意touchstart事件觸發之后還會觸發原監聽的click事件

可按需來把它注銷掉,移動端即有如絲般順滑的collapse

// 移動端iOS click有延遲  添加折疊的touchstart事件支持
        if (isiOS) {
            $(document).off('click.bs.collapse.data-api', '[data-toggle="collapse"]');

            $(document).on('touchstart.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
                var $this   = $(this), href
                var target  = $this.attr('data-target')
                    || e.preventDefault()
                    || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
                var $target = $(target)
                var data    = $target.data('bs.collapse')
                var option  = data ? 'toggle' : $this.data()
                var parent  = $this.attr('data-parent')
                var $parent = parent && $(parent)

                if (!data || !data.transitioning) {
                  if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
                  $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
                }

                $target.collapse(option)
            });
        }

 

10. iOS10+會忽略meta 標簽的user-scalable=no,沒錯蘋果就是那么牛別

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no">

頁面要禁止用戶縮放,可以使用JS來輔助處理

// 禁止縮放  iOS10+會忽略meta的user-scalable=no
        document.documentElement.addEventListener('touchstart', function (event) {
            if (event.touches.length > 1) {
                event.preventDefault();
            }
        }, false);

另外要注意的是,上面只是禁用了雙指的縮放,還有一種縮放叫做雙擊縮放,而iPad下是沒有雙擊事件的,所以只能模擬

引用st上的一段雙擊事件支持

(function($){
            // Determine if we on iPhone or iPad
            var isiOS = false;
            var agent = navigator.userAgent.toLowerCase();
            if(agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0){
                   isiOS = true;
            }

            $.fn.doubletap = function(onDoubleTapCallback, onTapCallback, delay){
                var eventName, action;
                delay = delay == null? 500 : delay;
                eventName = isiOS == true? 'touchend' : 'click';

                $(this).bind(eventName, function(event){
                    var now = new Date().getTime();
                    var lastTouch = $(this).data('lastTouch') || now + 1 /** the first time this will make delta a negative number */;
                    var delta = now - lastTouch;
                    clearTimeout(action);
                    if(delta<500 && delta>0){
                        if(onDoubleTapCallback != null && typeof onDoubleTapCallback == 'function'){
                            onDoubleTapCallback(event);
                        }
                    }else{
                        $(this).data('lastTouch', now);
                        action = setTimeout(function(evt){
                            if(onTapCallback != null && typeof onTapCallback == 'function'){
                                onTapCallback(evt);
                            }
                            clearTimeout(action);   // clear the timeout
                        }, delay, [event]);
                    }
                    $(this).data('lastTouch', now);
                });
            };
        })(jQuery);

然后就可以簡單地進行調用了,雙擊后執行e.preventDefault()即可

$(document).doubletap(
                    /** doubletap-dblclick callback */
                    function(event){
                        event.preventDefault();
                    },
                    /** touch-click callback (touch) */
                    function(event){
                    },
                    /** doubletap-dblclick delay (default is 500 ms) */
                    100
                );

 

11. requestAnimationFrame的並行調用不能保證在不同幀執行

希望的效果是在一幀一幀地執行,然而瀏覽器會將多個操作合並到同一幀中,檢測發現

有分幀的策略,但得在回調中再次調用requestAnimationFrame才行

而實際操作中還需要一種並行調用就能分幀的方案,目前還沒找到

然而文檔中也指明了,是會放到同一幀的,所以估計這思路沒戲了

 

12. iOS高版本中,在微信內訪問網頁,音頻背景音樂無法自動播放

其實在高版本瀏覽器中,基於安全措施,已經不允許自動播放音頻了,但在微信內是可以的

微信安卓環境下正常,但在高版本的iOS下就失效了,解決辦法是在微信的WeixinJSBridgeReady事件中播放即可

        document.addEventListener('WeixinJSBridgeReady', function() {
                ...
                audio.play();
                ...
            }, false)

 

13. 分享微信頁面到朋友圈時,沒有圖片logo

文檔中指明了要只用絕對路徑,即協議名、域名、路徑等等都要寫全,漏寫了就沒了

另外,路徑要填寫微信能夠訪問的地址,不能是內網的

 

14. 在某些手機的微信中,分享頁面成功后,會有已分享的提示信息,但有些手機卻沒有

所以開發頁面的時候,還得自行加個已分享的回調提示,心桑..

 

15. 測試的時候發現,微信里頁面的touchstart事件是不能取消的,即cancelable==false,在安卓的UC和Chrome中是為true的

 

16. 在smarty環境下,通過后端拿到了一個變量值放在a標簽的href屬性中,點擊后跳轉的鏈接不對,

即鏈接直接附在了當前頁面url的后面,將http:// 替換成 // 卻成功了,這還不知為啥..

 

17.  z-index有拼爹的性質,

z-index值只決定同一父元素中的同級子元素的堆疊順序。父元素的z-index值(如果有)為子元素定義了堆疊順序(css版堆疊“拼爹”)

要注意這個特性,另外要提及的是,z-index只有設置了非static的position值才能生效

 

18. 可編輯的元素,即設置了contenteditable為true的元素是可編輯的,它有個光標的坑

當設置元素的內容innerHTML改變時,原先的光標位置會直接 跑到前面,這個不好解決

跟光標相關的還有選中位置的值的處理

假如要實現contenteditabletrue的元素中內容的復制和粘貼功能,簡單地復制粘貼就會取到錯亂的HTML標簽

結合getSelectionclipboardData相關的操作(還得注意這個對象在新版瀏覽器中以及移到了原生事件對象originalEvent下,之前是在ClipboardEvent對象下),

可以實現出來,不過並不是很完美,反正就是不好搞

// 標題組件粘貼
            .on('paste', '.component-title', function(e) {
                if (that.previewing) { return; }

                e.preventDefault();

                var $this = $(this),
                    $title = $this.find('.title'),
                    t = e.originalEvent.clipboardData.getData('text/plain'),
                    s = window.getSelection(),
                    oldTitle = $title.text(),
                    startOffset = s.anchorOffset < s.focusOffset ? s.anchorOffset : s.focusOffset,
                    endOffset = s.anchorOffset > s.focusOffset ? s.anchorOffset : s.focusOffset,
                    start = oldTitle.slice(0, startOffset),
                    end = oldTitle.slice(endOffset);

                $title.html(start + t + end).attr('data-title', start + t + end);
            })

 

19. 有一種坑、或者說是特性叫做 Font Boosting,這個特性也叫做 Text Autosizer,

現象就是字體的顯示大小,與在CSS中指定的大小不一致

是 Webkit 給移動端瀏覽器提供的一個特性:當我們在手機上瀏覽網頁時,很可能因為原始頁面寬度較大,在手機屏幕上縮小后就看不清其中的文字了。而 Font Boosting 特性在這時會自動將其中的文字字體變大,保證在即不需要左右滑動屏幕,也不需要雙擊放大屏幕內容的前提下,也可以讓人們方便的閱讀頁面中的文本。

實踐中發現可以通過設置容器的max-height高度來實現,可以前去上述文章查看更多

    /* 有滾動條時 基於瀏覽器自身對字體的自動縮放,容器里的字體可能會變大,可定義一個屬性避免 */
            .job-type_list {
                max-height: 999999px;
            }

 

20. 這問題太久遠都忘了,直接放個圖吧

21. 有個HTML5的視頻插件叫做 Video.js,要實現視頻海報的大小占滿視頻大小的話

直接設置width、height無效,設置background-size: cover 可以解決

 

22. 有個彈窗組件叫做 Layer.js,發現個問題是在layer彈出層中播放視頻,視頻的全屏按鈕失效

沒啥辦法了,最后直接暴力地解決了

 

23. React的componentWillReceiveProps事件調用的時機還不太清晰,

雖然文檔中已經寫明了

在測試過程中發現,就算父組件不傳遞props,子組件的這個方法也會被調用,還不知道為什么

也許是做淺比較 {} !== {}  吧 ?

 

24. React 的componentDidUpdate事件調用的時機還不太清晰,

雖說是在組件更新之后才調用,不過在一個復雜頁面中測試發現,componentDidUpdate已經觸發了,但卻獲取不到頁面中的元素(看起來像是組件還沒更新完成)

不知為啥,最后只能加個定時器處理了

 

25. React 的componentDidMount事件調用的時機還不太清晰,

雖說是在組件加載完成之后才調用,但在實踐中的一個需求發現一個問題,不太好解決,查了蠻久還沒看到合適的方案

比如要做一個彈窗組件,包含幾個component,彈窗是調用子component出來,原想在調子component的時候才觸發其componentDidMount事件,不料早在頁面加載時所有component的componentDidMount事件就已經觸發了,心桑..

 

26. jshint對redux中某些語法報錯,需要做一些處理

在文件起始處加上 /* jshint -W138 */ 即可

 

27.  排除由 input[type="file"] 點擊引起的 window.onblur事件

很簡單,使用document.activeElement 來處理即可

 

28.  在離開當前頁面時判斷是否有更改,做出提示

新版本瀏覽器基於安全機制,不能設置提示的樣式,也不能設置提示中操作(確認和取消)的回調,也不能設置提示的文案(舊版的可以設置文案)

實現檢測提示的方法很簡單,例如

// 離開當前頁面之前,判斷是否有更改,做出提示
        window.onbeforeunload = function (e) {
            // 內容有改變且不是提交試卷之后的觸發
            if (this.state.changed && !this.state.saved) {
                return '提示:當前內容有修改';
            }
        }.bind(this);

 

29. chrome59以上的已經不支持頁面引入ftp文件了

 

30. 有個編輯器叫做 wangEditor,也有一些坑

wangEditor默認的吸頂 滾動會影響頁面上position: fixed的元素 可依據文檔中配置為false

word文檔中復制帶換行的內容到編輯器中會有亂碼,如

調試找到了解決辦法,改了源碼,給作者提了個pr就好了

 

31. requirejs可以使用urlArgs參數自定義文件是否緩存

 

32. checkbox和radio的樣式基本是很難自定義的,一種解決方式是用其他方式模擬出來

比如用-webkit-appearance: menulist 模擬下拉框,用 圓角的span模擬radio

   

而下拉框的樣式在手機上是調用原生內核的(瀏覽器的或WebView的),為了保證一致的效果(在測試過程中發現華為機型經常出現不一致的問題),可以統一用ul來模擬安卓下的下拉框彈層選擇,在iPhone下保持其原生即可

 

33. 有個插件叫做 jx-xlsx,可以用來給前端讀取excel文件里的內容

 

34. 有個編輯器叫 Ueditor,也有一些坑

它會在全局設置ul 和 li 的list-style為none,導致改出現的列表樣式消失了

還有一些與奇葩需求結合的坑,忘得差不多了

 

35. “微軟雅黑” 和 “Microsoft YaHei”是有區別的,tell me why ~

 

36. 有時已經開啟了Gzip壓縮,但從timeline上看似乎是全量下載了,且看

因暫重現不了,先用一幅圖表示,TTFB 是幾百ms左右,但Content Download卻有十幾秒

這種情況還不知為啥,但過一段時間又好了

又測到里,一般出現中服務器剛啟動的時候,過了一會才好

 

對 TTFB 的理解還不夠清晰,在測試中發現,頁面加載資源緩慢

而頁面基本不需要后端操作,所以后端的耗時應該不是主要的,也部署了CDN節點,所以首個報文頭部傳輸太慢應該也不是主要的

后來發現,對頁面中資源的請求又亂了,從timeline瀑布流中發現資源並不是按照頁面代碼順序由上往下請求,比如<img 標簽中的src資源和css文件中的background-image屬性中的src資源加載的順序,資源並行加載的數量不清晰

一堆的不清晰之中,嘗試盡可能地在減小請求數與減小資源大小直接做平衡,

盡可能地讓關鍵的資源在最先的並行順序中加載,頁面整體加載感覺就快多了

難點TTFB還與資源的加載時機有關?還得多查查

 

37. 表格中有大量數據時,很容易就會出現性能問題

表格ReflowRepaint代價都很高,在滾動、對表格項操作的時候,經常就卡頓了

優化方案得按實際需求來看

首先可以嘗試:盡可能地只處理視窗可見的表格項即可,這樣一來性能就可以翻個幾十倍

然后嘗試:盡可能避免不必要的Reflow和Repaint,CSSTriggers關於樣式的,以及關於JS的DOM屬性

然后嘗試:盡可能地緩存,不必要的計算就不計算,十萬項,每項節約0.01ms,那都能減少1s的卡頓

然后:優化DOM選擇器等等

 

38: 移動端的動畫常常會碰到卡頓問題,多半是掉幀太嚴重了

關於幀的知識點,還得多去理解requestAnimation、GPU、JS的事件循環機制、setTimeout/setInterval 、瀏覽器繪制原理等等

基本原則是大多數情況下用setTimeout,上戰場時盡量避免setInterval,別忘了requestAnimation這個好助手,合理分配Composite Layer

還得多實踐才能發現更多坑

 

39. 頁面上可播放的視頻大多需要是mp4格式的,且其格式需是H.264,否則某些情況下會碰到有聲音沒畫面的現象

 

40. Angular.js(1)中經常會碰到 In Progress 的錯誤問題

估計是經驗還不夠吧,經常操作后就調用$scope.$apply()

解決方式就是多用$scope.$digest()代替,更好的方式是把操作放到$timeout$http等會自檢查的地方中

 

41. 在數據量大的時候,Angular.js(1)中的input只要放到了$scope相關域之中,就一卡一卡的

知道了原因,是因為大數據量的頁面中綁定太多,很多數據需要ng-bind,導致input一用上雙向綁定就得檢查所有數據

中性能面板匯總可以看到,在鍵盤按下和松開的時候,會觸發Angular的keypress和keyup事件,每個耗時幾百毫秒

解決辦法就是對不需要綁定的數據,盡量不用Angular自建的綁定,換成普通方式就好(如JQ的綁定)

目前在Angular中還比較濫用JQ,以后得多注意

關於Angular的性能優化也有很多需要去慢慢了解,比如 speeding-up-angular-js-with-simple-optimizations 

 

42. 在數據量大的時候,Angular.js(1)重新更新視圖(ng-repeat)會很卡,目前還沒比較好的方案

而在更新數據操作的前一步,展示一個loading效果,竟會卡上好幾秒,然后loadIng才出來就立馬結束

可能是線程太繁忙GUI無法繪制?嘗試將操作放到下一輪事件循環中或使用requestAnimationFrame,loading能按照預期顯示出來,但視圖卻更新不成功

最后只能再加個$scope.$digest()了

 

而為了監聽ng-repeat是否執行完,視圖是否更新成功也耗了不少功夫

目前發現三個方法

-> 指令

angular.module('myApp', [])
.directive('repeatFinish', function() {
    return function(scope, element, attrs) {
        if (scope.$last) {
         // 向父域發布事件
          scope.$emit('repeatFinishEvent');
      }
    };
});
<div ng-controller="Ctrl">
  <div class="thing" ng-repeat="thing in things" repeat-finish>
    thing {{thing}}
  </div>
</div>

->  控制器

angular.module('myApp', [])
.controller('repeatFinish', function($scope) {
        if (scope.$last) {
         // 向父域發布事件
          scope.$emit('repeatFinishEvent');
      }
});
<div ng-controller="Ctrl">
  <div class="thing" ng-repeat="thing in things" ng-controller="repeatController">
    thing {{thing}}
  </div>
</div>

-> $eval調用

直接中想監聽的地方之后調用,如

// loading ...

$timeout(function() {
    $scope.$eval(function() {
        // clear loading ...
    });
});

 

實際中發現,第一第二種方法只有中第一次的時候成功,后來似乎都不觸發了

后來就采用了第三種方式直接上了

相關討論:ng-repeat-finish-event  calling-a-function-when-ng-repeat-has-finished

 

43. Angular.js(1)的ng-repeat中過濾空的數據,在 討論 中看到有好幾種寫法

但是都失效..

 

44. mouseenter和mouseleave事件冒泡產生的問題,為了實現鼠標划過tr標紅,划出tr取消標紅

而由於冒泡的問題,划過的td時候就觸發了父tr的mouseleave事件,所以加句

e.stopPropagation();

 

45. 使用webpack編譯的過程中發現,文件耦合略為嚴重

假設webpack要編譯15個頁面文件,因為需要提取一個common.js文件,只改一個字,15個頁面文件引用的common.js就得改

基於資源加戳,則這些頁面都有改動了

如果某個React組件被共用了,改動到一半的時候有線上問題要插單,那么已經做的修改就只能按文件備份了,實在是不好管理

 

46. webpack編譯耗時過長,該如何優化

目前加上了chunkhash,相對好了一些,但還是有不夠快,可能還需要減少打包的文件數量,再看看吧

 

47. webpack打包后自動更新頁面的資源路徑

目前用着兩種方式

使用 html-webpack-plugin 插件,提供模版文件及目標文件,不過好像生成的路徑有點問題,基本還得自己再調整一下

直接讀取文件修改占位,提供模版文件和目標文件,Node.js

this.plugin('done', function(stats) {
                let asset = stats.toJson().assets;

                // console.log(asset);

                let commonItem = asset.filter(function(item) {
                    return item.chunkNames[0] === 'common';
                });

                asset.forEach(function(item) {
                    if (!files[item.chunkNames[0]] || item.chunkNames[0] === 'common') {
                        return;
                    }

                    fs.readFile(files[item.chunkNames[0]].src, 'utf-8', function(err, doc) {
                        if (err) {
                            throw err;
                        }

                        doc = doc
                            .replace('%' + item.chunkNames[0] + '.js%', item.name)
                            .replace('%common.js%', commonItem[0].name);

                        fs.writeFileSync(files[item.chunkNames[0]].dest, doc);
                    });
                });
            });

 

48.  在PC上和模擬器上內容是垂直居中的,但在真機上內容卻偏上了一丟丟

 在華為小米中發現過

 

49. 表格的表頭、首行或首列固定等

表格數據多時,需要有個滾動時把某一信息行列固定的效果,方案有兩種

->直接設置該行列的position

這是最直接的,在一般表格中可以使用,但數據量很多的時候,或者表頭復雜(比如colspan=4等)的時候就不建議使用了,計算復雜且耗性能

->把需要固定的元素復制過來成新的表格,在需要的時候整個一起操作

這中方式可以很好地處理復雜表格的問題,且計算方式也容易一點

 

表格固定最大的難點在於保證固定項和內容項的寬高一致,在完全自適應內容的情況下是非常非常難做到的(在復雜表頭的時候)

所以可以考慮做一些寬高的限制(比如width或設置max-width也可以)

其實主要就是在開始時遍歷每一項所計算的寬高,賦值到固定表頭的屬性中,用colgroup輔助的效果會好一些,如

            <colgroup>
                        <col width="12%"></col>
                        <col width="8%"></col>
                        <col width="8%"></col>
                        <col width="30%"></col>
                        <col width="10%"></col>
                        <col width="8%"></col>
                        <col width="8%"></col>
                        <col width="15%"></col>
                    </colgroup>        

 

另外,記得關注表頭固定產生的性能問題

 

50. 在iPad中,輸入中文,輸完拼音然后選中文的時候是不會觸發onkeyup事件的

 這個問題在監聽了keyup事件的時候會出問題,最后檢測到的只是拼音

解決辦法是加上input或change事件

 

51. 數據量大滾動時的卡頓,可以嘗試加上will-change: transform來避免重新布局

在幾萬條數據的表格中試過,因為每條數據又有一些綁定,導致每次渲染都有卡頓現象,滾動的時候一卡一卡的

滾動時,在性能面板中發現耗時全出在了Recalculate Style上,使用一個屬性即可避免這一問題  reducing-scroll-jank-when-using-overflow-y-scroll

.wrap {
    width: 100%;
    height: 100%;
    overflow: auto;
    will-change: transform;
}

 

52. 導出帶鏈接的數據到Excel表中,點擊鏈接時,不會正確依據瀏覽器cookie信息訪問鏈接指向的頁面(如果該鏈接有判斷是否登陸的情況)

原因:微軟相關產品Word/Excel在打開鏈接時,自個會先去判斷這個鏈接是不是正確的屬於自家的,然后才跳到鏈接中

解決辦法一:鏈接的后端路由代碼中,判斷是否登陸時,增加對微軟的訪問頭部字段檢測,如果是,則直接返回over即可

如PHP中

if (isset($_SERVER['HTTP_USER_AGENT']))
{
    $http_user_agent = $_SERVER['HTTP_USER_AGENT']; 
    if (preg_match('/Word|Excel|PowerPoint|ms-office/i', $http_user_agent)) 
    {
        // Prevent MS office products detecting the upcoming re-direct .. forces them to launch the browser to this link
        die();
    }
}

不過這種頭部檢測貌似只在2013版中有效,中Excel2007或以下版本檢測不到

解決辦法二:新增一個中轉空白頁,導出數據時鏈接指向這個空白頁,鏈接中攜帶要跳轉的頁面鏈接。然后在空白頁中增加JS跳轉至URL中指向的頁面鏈接即可

缺點是會有短暫白屏,勉強可用

更多見討論

53. 新版Chrome(61以上)的Network面板Preview中不支持轉換返回數據為對象樹結構

 舊版本中支持,升級之后直接就變為純文本了

當然,還有bug是暗色主題的文本顏色竟然也是黑的..

原因是新版對JSON數據的解析比較嚴格了,需要Content-Type是json才會解析,當然,后端的接口也有問題,沒有指定好返回的格式為json

沒想到更好的解決辦法,可暫時通過Fiddler代理,判斷是異步請求后,替換返回的HTTP頭部字段即可

在FiddlerScript面板中,在這一部分中設置

 static function OnBeforeResponse(oSession: Session) {
        if (m_Hide304s && oSession.responseCode == 304) {
            oSession["ui-hide"] = "true";
        }
        
        // 修改異步返回的數據為json類型
        
        if (oSession.oRequest['X-Requested-With'] == 'XMLHttpRequest') {
            oSession.oResponse['Content-Type'] = 'text/json; charset=UTF-8';
        }
    }

54. 在Chrome開發者工具中打開開發者工具(Inspect in DevTools)

其實Chrome開發者工具就像是一個iframe,嵌入到頁面中,也是可以審查的

首先打開DevTools至獨立窗口中,然后在該獨立窗口的DevTools中使用快捷鍵(如Ctrl+Shift+J)打開即可

 

可以自定義修改一些樣式,不過好像只是暫時的,找不到相關文件的引入方式,果然密封得強!

 

55. Safari下new Date('yyyy-MM-dd HH:mm:ss') 會返回 Invalid Date ,在Chrome下正常

 這種錯誤多發生在移動端頁面,安卓機子下正常,iPhone下時間的轉換就出問題了

原因是Safari下的特殊性,導致解析失效,也是格式不標准的問題

解決方法:日期和時間用 T 分隔即可,即把中間的空格換成T 

更多 更多

 

56. 移動端動畫 -webkit-animation-play-state:paused; 暫停狀態在Safari瀏覽器中失效

在H5中播放音樂時,時常會用到播放時旋轉,點擊暫停,再點擊就繼續播放

為了實現這個效果,除了切換背景幀圖之外,可以直接用動畫操作rotate旋轉,配合animate的state屬性來用即可

  // -webkit-animation-play-state: running;
  // animation-play-state: running;

   -webkit-animation-play-state: paused;
   animation-play-state: paused;

 

在安卓環境下正常;在iPhone下一開始paused屬性有效,但當動畫動起來之后,再使用paused就會失效

這是safari瀏覽器的bug,解決辦法有三個:

1. 使用幀圖來變換圖標

2. 如果不是一定要記住暫停之后的狀態位置,再次播放時從頭開始的話,可以直接暫停的時候設置animation為none即可

   -webkit-animation: none;
   animation: none;

 

3.不過一般是偷工減料的,為了統一起來android和ios都能正常,可以利用JS獲取元素樣式之后,再進行更新,做一個狀態疊加

首先,需要給目標元素添加父外層做旋轉疊加時用

<a href="javascript:;" class="rule-btn"></a>
<span class="music-btn-wrap"><a href="javascript:;" class="music-btn"></a></span>

默認目標元素是不會動的,當可以動的時候(有類on的時候)就旋轉

.music-btn.on {
      animation: .....
}

點擊時加上一些狀態樣式變更操作,注意此處需要將父外層與子元素的transform樣式進行疊加

$('.music-btn').click(function() {
            var $this = $(this);

            var musicTransform = getComputedStyle(this).transform;
            var musicWrapTransform = getComputedStyle(this.parentNode).transform;


            if ($this.hasClass('on')) {
                audio.pause();
                $('.music-btn-wrap').css('transform', musicWrapTransform === 'none' ? musicTransform : musicTransform.concat(' ', musicWrapTransform))
                $('.music-btn').removeClass('on');
            } else {
                audio.play();
                $('.music-btn').addClass('on');
            }
        })

 

57. iPhone的safari與Mac的safari進行遠程調試時,MAC的iOS系統不能比iPhone的低,否則無法連接上,即“開發”菜單欄下的看不到連接的iPhone信息

 

58. iPhone或iPad的safari瀏覽器不支持 <object>或<embed>來嵌入pdf預覽

一般來說,預覽pdf文件可以直接在html中嵌入<embed>,標明type類型即可調用瀏覽器自身的插件來預覽

 <embed src="pdfPath" width="100%" height="100%" type="application/pdf" />

在Mac上的safari是能嵌入的,不過在iPhone或iPad下失效,但是能直接通過鏈接打開,所以解決辦法是通過<iframe>嵌入pdf文件的地址,不過還有問題,見下一個

59.  iPhone或iPad的safari瀏覽器通過<iframe>嵌入pdf來預覽時,只能看到第一頁,無法滾動翻頁查看更多

這個問題是ios自家的bug了,所以為了解決,只能引入第三方支持(不再使用瀏覽器自身支持的pdf預覽) 詳見 

第三方支持主要有兩個:google doc 的,pdf.js

推薦使用pdf.js,簡單講下大致用法,可直接去看使用文檔

https://github.com/mozilla/pdf.js

https://github.com/mozilla/pdf.js/wiki/Setup-PDF.js-in-a-website

第一種是用git拉取下來之后再用gulp來編譯生成,再使用

當然,懶的話,就直接下載下來,使用

入口主要是這個文件

當然,也可以不下載,直接使用mozilla提供的來使用,不過需要解決一下跨域問題

 

60. iframe 的 visibility hidden屬性在safari中失效

一個bug,解決辦法是用opacity:0|1來代替,或者直接display:none

 

61. 在頁面中預覽doc、docx文檔時,可以使用第三方鏈接,設置需要預覽的文檔路徑即可

 詳見

第一種是使用Google Docs Viewer

<iframe src='https://view.officeapps.live.com/op/embed.aspx?src=http://remote.url.tld/path/to/document.doc' width='1366px' height='623px' frameborder='0'>This is an embedded <a target='_blank' href='http://office.com'>Microsoft Office</a> document, powered by <a target='_blank' href='http://office.com/webapps'>Office Online</a>.</iframe>

第二種是使用Microsoft Office Viewer

<iframe id="pdf-iframe" src="https://view.officeapps.live.com/op/embed.aspx?src=SRC“ frameborder="0"></iframe>

推薦用第二種,因為第一種可能被牆..

另外要注意使用絕對路徑,且是能被外網訪問的路徑

 

62. chrome61中已經不支持使用document.body.scrollTop來獲取頁面的垂直滾動距離,可改用document.scrollingElement.scrollTop

 一般來說,獲取頁面的垂直滾動位置通常使用document.body.scrollTop,其實這並不是標准的做法,屬於舊規范里面的

在標准規范里是用document.documentElement.scrollTop來獲取,不過chrome以往的webkit內核兩種都是支持的,今天發現更新的chrome61版本已經不再支持舊的做法,導致一些頁面滾動相關的操作失效

當然,這里的標准規范是值<html>指明的是標准的,如

<!DOCTYPE html>
<html>

如果是舊規范的標准,那用document.body來獲取還是可以的

<html xmlns="http://www.w3.org/1999/xhtml">

 

解決辦法:

使用新標准制定的document.scrollingElement.scrollTop獲取,同時兼容舊的

var rootElement = document.scrollingElement || document.body;

if (rootElement.scrollTop > 0) {
        $goTop.show();
}

更多   更多

 

63. chrome61中,某些情況下,頁面滾動到底部(有滾動條),點擊select,input, textarea等相關項時,會自動滾動到頁面頂部

在chrome60中還是正常的,一升級就出現問題了

目前還不知道為何,可能是chrome61的bug?

更多  

 

64. WebUploader 選擇文件的按鈕(picker)點擊時沒反應(button作容器,且有padding值)

 WebUploader是一個上傳文件的插件,功能強大,不過bug還是很多的,然而官方已經很少維護了

設置picker的選擇文件按鈕后,時常點擊無效(並不是重復選擇文件、按鈕初始被隱藏的無效)。后來發現是點擊中間時可以,但點擊邊緣就沒反應

看了源碼發現,文件input[file]項是通過點擊label模擬觸發的

而label的可點擊區域實際上是上圖中的元素

可以發現主要原因是計算元素的寬高出錯,導致點擊區域不正確。

沒有好的解決辦法,只好取消button的padding,用多余的寬高來代替,並且顯示設置.webuploader-pick 占滿父元素

.webuploader-pick {
        width: 100%;
        height: 100%;
        line-height: 28px;
    }

#upload-artWorks-picker {
    padding:0;
    width:70px;
    height:30px;
}

 

65. 迅雷會檢測並自動下載HTML5中Video標簽中設置的.mp4視頻

如果機子裝了迅雷,在設置Video源的時候(比如使用video.js或用原生)並不會播放,而是自動被迅雷調出下載

可以說是迅雷流氓了,它自動檢測http流的數據

解決辦法一:不用http流的,改用其他流媒體

解決辦法二:mp4格式的文件Response Header中的Content-Type默認是 application/octet-stream,后端設置返回頭部Response Header中的值,把Content-Type修改為video/mp4即可

 

66. Mac的Safari中觸發input[type="file"]點擊失效

safari下會有很多安全性的問題,關於文件選擇項的觸發,原生的文件選擇框的樣式不太好修改,一般會隱藏掉然后用一個輸入框代替,點擊后再觸發文件的選擇

在safari下會失效,解決辦法是在包裹的label 元素中加上for參數即可

                    <label for="file">
                            <span>附件</span>
                            <input type="file" class="fileFile" data-val="{{AttachFileName}}" accept=".rar,.zip">
                            <input type="text" class="form-control input-sm fileInput" placeholder="請選擇文件" readonly >
                        </label>

 

67. Firefox中的readonly input項有光標,在Chrome中無光標

是一個bug,解決辦法對改元素設置disabled屬性,不過這種方式副作用比較大

推薦使用事件監聽的方式

    $(document).on('focus', 'input[readonly]', function() {
            this.blur(); // 或 this.select()
        })

 

 

68. Chrome新版本的插件列表中默認沒有Shockwave Flash,某些Flash播放器會失效(如果播放前查詢插件是否存在)

在比較舊的瀏覽器中是可以正常播放Flash視頻的,有直接就能播放的,也有提示選擇打開Flash進行播放的

但在新版Chrome中(如62),連提示都沒有了,需要手動在設置中添加Flash支持的網站例外才能播放

看了所用的Flash播放器(CuPlayer),播放前是先檢測插件是否存在的,這造成了在新版Chrome中檢測不到插件的存在,從而初始化不了播放器

暫時的解決辦法是,稍微修改一下播放器的源碼,在特定的時候傳個參數,就不檢測Flash是否存在了,直接使用即可,就可以讓Chrome出現打開Flash的提示

允許一次之后,當前域名端口的一條記錄就會被添加到例外中,重新刷新,Flash插件就存在列表中了

(舊版不影響)

 

 

69. 修改本地時間,調用 new Date() 獲取時間會有延遲

修改本地時間后,這個獲取時間某些情況下會不正確。原因是瀏覽器自身緩存了當前時間值。

當修改的時間變化比較小時(比如改變幾分鍾)能更新到正確的值

改變比較大時(比如改變幾十分鍾或幾天),這個值在一分鍾左右才會更新出來

 

70. Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

在React中使用第三方插件(比如jQuery)來更新DOM樹結構時,會出現類似這種錯誤。

React只對內部的DOM樹及狀態負責,外部插件修改之后(比如將某個節點拖動到另一個節點),再更新state來重新渲染,就會出問題

 

71. 待續

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM