URLSearchParams 兼容性引发IOS 10 白屏问题

在使用公司平台提供的组件时,遇到在6s、7p时出现白屏情况,通过review代码发现平台的组件使用了URLSearchParams和es6 的includes。

通过caniuse.com 或者MDN查看 URLSearchParams兼容发现,对于低版本的IOS 10.3 ( 2017 年 3月发布)以下是不支持的。

URLSearchParams 兼容性引发IOS 10 白屏问题_第1张图片

使用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

乍一看这实现很简单很好修改,直接使用字符串拼接方式:

URLSearchParams 兼容性引发IOS 10 白屏问题_第2张图片

对于简单的参数(字符串,数字)这样处理是没有问题的,如果传入的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

你可能感兴趣的:(HTML5,Web前端,兼容性,URLSearchParams,白屏,IOS,10)