URLSearchParams 兼容性引發IOS 10 白屏問題

在使用公司平臺提供的組件時,遇到在6s、7p時出現白屏情況,通過review代碼發現平臺的組件使用了URLSearchParams和es6 的includes。

通過caniuse.com 或者MDN查看 URLSearchParams兼容發現,對於低版本的IOS 10.3 ( 2017 年 3月發佈)以下是不支持的。

使用URLSearchParams 實現URL拼接源碼:

export function contactUrl (url = '', params = {}) {
  let qs = new URLSearchParams()

  for (let key in params) {
    qs.append(key, params[key])
  }

  if (url.includes('?')) {
    return url + '&' + qs.toString()
  } else {
    return url + '?' + qs.toString()
  }
}

如何解決?

1、使用url-search-params-polyfill 

2、自己使用字符串拼接URL

乍一看這實現很簡單很好修改,直接使用字符串拼接方式:

對於簡單的參數(字符串,數字)這樣處理是沒有問題的,如果傳入的params 中存在特殊參數(加密串),這種簡單處理就出現無法匹配的問題了。

項目中正好有個特殊參數加密session_id ,使用上面的實現出現無法通過校驗的問題。對比2個方式的請求URL發現session_id長度不一致,嘗試過多種方式都無效,最後參考url-search-params-polyfill 是如何實現的。

URLSearchParamsPolyfill源碼分析

在url-search-params-polyfill的 index.js 中,我們看到append(name, value)的實現是調用appendTo() 將name, value 作爲一個數組的key , value 存儲在this身上。

直接看appendTo(dirct, name ,value) 方法(append 調用中dirct 指向 對象this):

  function appendTo(dict, name, value) {
        var val = typeof value === 'string' ? value : (
            value !== null && value !== undefined && typeof value.toString === 'function' ? value.toString() : JSON.stringify(value)
        );

        if (name in dict) {
            dict[name].push(val);
        } else {
            dict[name] = [val];
        }
    }

append 沒有特殊,再來看下URLSearchParamsPolyfill中的toString方法:

   prototype.toString = function() {
        var dict = this[__URLSearchParams__], query = [], i, key, name, value;
        for (key in dict) {
            name = encode(key);
            for (i = 0, value = dict[key]; i < value.length; i++) {
                query.push(name + '=' + encode(value[i]));
            }
        }
        return query.join('&');
    };

遍歷this對象每個元素,並對每個元素進行encode後拼接成參數字符('a=b&c=d')。

重點就在於對每個元素encode 方法,通過源碼分析它的實現並不是簡單進行encodeURIComponent , 同時進行了字符串進行編碼escape。

    function encode(str) {
        var replace = {
            '!': '%21',
            "'": '%27',
            '(': '%28',
            ')': '%29',
            '~': '%7E',
            '%20': '+',
            '%00': '\x00'
        };
        return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function(match) {
            return replace[match];
        });
    }

看到這裏就已經很明瞭,URLSearchParams在對象調用toString時對元素參數進行的處理。

最後在自我實現的方法拼接字符串的時候添加相應的字符編碼處理,把問題解決了。

參考資料:

url-search-params-polyfill

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章