兼容和Error捕获

兼容

IE兼容

  • ie没有forEach
if(!Array.prototype.forEach) {
    Array.prototype.forEach = function(fun){
        var len = this.length;
        if(typeof fun != "function"){
            throw new TypeError();
        }
        var thisp = arguments[1];
        for(var i = 0; i < len; i++){
            if (i in this){
                fun.call(thisp, this[i], i, this);  
            } 
        }
    }
}  
  • ie没有trim
String.prototype.trim=function(){
    return this.replace(/(^s*)|(s*$)/g,"");
}  
  • ie没有json
if (!window.JSON) {
    // 添加json对象      
    window.JSON = {
        parse: function(jsonStr) {
            console.log(123)
            return eval('(' + jsonStr + ')');
        },
        stringify: function(jsonObj) {
            var result = '',curVal;
            if (jsonObj === null) {
                return String(jsonObj);
            }
            switch (typeof jsonObj) {
                case 'number':
                case 'boolean':
                    return String(jsonObj);
                case 'string':
                    return '"' + jsonObj + '"';
                case 'undefined':
                case 'function':
                    return undefined;
            }
            switch (Object.prototype.toString.call(jsonObj)) {
                case '[object Array]':
                    result += '[';
                    for (var i = 0, len = jsonObj.length; i < len; i++) {
                        curVal = JSON.stringify(jsonObj[i]);
                        result += (curVal === undefined ? null : curVal) + ",";
                    }
                    if (result !== '[') {
                        result = result.slice(0, -1);
                    }
                    result += ']';
                    return result;
                case '[object Date]':
                    return '"' + (jsonObj.toJSON ? jsonObj.toJSON() : jsonObj.toString()) + '"';
                case '[object RegExp]':
                    return "{}";
                case '[object Object]':
                    result += '{';
                    for (i in jsonObj) {
                        if (jsonObj.hasOwnProperty(i)) {
                            curVal = JSON.stringify(jsonObj[i]);
                            if (curVal !== undefined) {
                                result += '"' + i + '":' +curVal + ',';
                            }
                        }
                    }
                    if (result !== '{') {
                        result = result.slice(0, -1);
                    }
                    result += '}';
                    return result;

                case '[object String]':
                    return '"' + jsonObj.toString() + '"';
                case '[object Number]':
                case '[object Boolean]':
                    return jsonObj.toString();
            }
        }
    };
}  
  • ie没有xhr(jq做了兼容)
  • ie没有addEventListener(jq做了兼容)
  • ie没有event.stopPropagation(改成e.cancelBubble=true)
  • ie没有event.preventDefault(改成window.event.returnValue = false;//注意加window)
  • ie没有console.log(改成alert)

苹果手机

  • 苹果手机日期转时间不支持"xxxx-xx-xx",只能用"xxxx/xx/xx"
  • 苹果手机键盘回弹页面不回弹,移动开发软键盘兼容
document.body.addEventListener('click',function (e) {
   if(e.target.type == "text" || e.target.type == "password" || e.target.tagName == "TEXTAREA" ){
	var nowTop = document.documentElement.scrollTop || document.body.scrollTop || 0;
	e.target.addEventListener('blur',mimeBlur)
	function mimeBlur() {
	    var e = event || window.event;
	    e.target.removeEventListener('blur',mimeBlur)
	    setTimeout(function() {
		window.scrollTo(0,nowTop);
	    }, 100);
	}
   }
})
  • 苹果的画布内容大小不能大于3m (这个无解)
  • 移动端input只读属性在iOS上点击还是有光标
<input type="text" unselectable="on" οnfοcus="this.blur();" readonly />
// unselectable属性作用 
// 在IE浏览器中,当input获得焦点时,点击有unselectable=”on”属性的标签时,不会触发onblur事件。 
// onfocus=”this.blur()”方法作用 
// 获取焦点时调用失去焦点事件
  • 苹果手机没有window.open方法

安卓手机

  • 安卓手机的微信分享API不能用1.4的js-sdk(继续用即将废弃的写法)
  • 安卓需要去除300毫秒的双击延迟,原因和解决方案

所有手机

  • fixed弹窗上添加输入框,点击输入框,如果最底层页面没有滚动条,可以把fixed改成absolute,如果最底层页面有滚动条,弹出的手机键盘会把最底层页面往上推,弹窗却不会上移,导致键盘遮挡输入框,解决方案是记录页面的滚动高度,把底层页面设置超出隐藏禁止滚动,等关闭弹窗再恢复滚动,并自动滚动到原位置,下面附上小程序的代码,原生js同理进行修改就行
<view style="{{hide ? 'height:100vh;overflow:hidden;' : ''}}">
   ...
</view>
<van-popup
  show="{{ showMask }}"
  bind:close="closeMask">
  <input value="{{ value }}" />
</van-popup>
data:{
   scrollTop: 0,
   scrollTop2: 0,
   hide: false,
   showMask: false,
   value: "在fixed里的输入框"
},
// 页面滚动触发事件的处理函数
onPageScroll: function (e) {
  this.setData({
    scrollTop: e.scrollTop
  })
},
openMask:function(){
  this.setData({
    hide: true,
    showMask: true,
    scrollTop2: this.data.scrollTop
  })
},
closeMask:function(){
  this.setData({
    hide: false,
    showMask: false,
  })
  wx.pageScrollTo({
      scrollTop: this.data.scrollTop2,
      duration: 0
  })
},
  • 滚动穿透,就是有一个弹窗,滚动到顶端和底端再接着滚动会变成滚动页面的滚动条,所以需要去阻止A层的滚动事件,但是直接阻止A层的滚动是会导致B也不能滚动,自己亲测,所以有什么时候阻止A的滚动就需要一个全局变量,上代码
<div class="A" style="position: fixed; 100%;height: 100%;overflow: hidden;top: 0;left: 0;background-color: rgba(100,100,100,0.5);"> 
  <div class="B" style="position: absolute;  80%;height:50%;left: 50%; top: 50%;transform: translate(-50%,-50%);overflow: scroll;">
     <div>
	<div style="height: 100vh;"></div>
	<div style="height: 100vh;"></div>
     </div>
  </div>
</div>
var y = 0;
var flag = true;
function ts(){
    y = event.targetTouches[0].clientY
    flag = false;
}

function tm(){
    var top = this.scrollTop
    // 这里取的是第一个子元素,所以不管B里面放多少东西,都要用个div装在一起 
    var ch = $(this).children().eq(0).height()
    var h =  $(this).height()
    if(event.targetTouches[0].clientY < y){
        // 向下
        if(top > ch - h - 50){
            event.preventDefault()
        }
    }else{
        // 向上
        if(top < 50){
            event.preventDefault()
        }
    }
    y = event.targetTouches[0].clientY
}
function te(){
    flag = true
}

function ftm(){
    if(flag){
        event.preventDefault()
    }
}

function addtouchFun(className,flagClass) {
    $('.'+className).on('touchstart',ts)
    $('.'+className).on('touchmove',tm)
    $('.'+className).on('touchend',te)
    if(flagClass){
        $('.'+flagClass).on('touchmove',ftm)
    }
}
// 使用
addtouchFun('B','A')

微信浏览器

  • 手机端和微信端添加了autoplay以后还是不可以自动播放,这是因为手机端为了节约流量所设置的
//这也不行就得用接口签名之后再ready里执行play了
document.addEventListener("WeixinJSBridgeReady", function () {
     audio.play();
}, false);
  • 微信的reload刷新地址无效
// location.reload()无效
location.href = location.href  + '_t=' + new Date().getTime()

上面的是开发过程中遇到的,其他文章有
移动开发兼容问题整理笔记
浏览器兼容性问题解决方案
渔人码头的经验

错误捕获

文章来自
错误拦截插件,付费

常见错误

  • JS 语法错误、代码异常
  • AJAX 请求异常
  • 静态资源加载异常
  • Promise 异常
  • Iframe 异常
  • 跨域 Script error
  • 崩溃和卡顿

错误捕获方式

  • 可疑区域增加 Try-Catch,try-catch 只能捕获到同步的运行时错误,对语法和异步错误却无能为力,捕获不到
  • 全局监控 JS 异常 window.onerror,onerror最好写在所有 JS 脚本的前面,否则有可能捕获不到错误
/**
* @param {String}  message    错误信息
* @param {String}  source    出错文件
* @param {Number}  lineno    行号
* @param {Number}  colno    列号
* @param {Object}  error  Error对象(对象)
*/
window.onerror = function(message, source, lineno, colno, error) {
   console.log('捕获到异常:',{message, source, lineno, colno, error});
}
  • 全局监控静态资源异常 window.addEventListener
window.addEventListener('error', (error) => {
    console.log('捕获到异常:', error);
}, true)
  • 捕获没有 Catch 的 Promise 异常:unhandledrejection
window.addEventListener("unhandledrejection", function(e){
  e.preventDefault()
  console.log('捕获到异常:', e);
  return true;
});
  • VUE errorHandler 和 React componentDidCatch
Vue.config.errorHandler = (err, vm, info) => {
  console.error('通过vue errorHandler捕获的错误');
  console.error(err);
  console.error(vm);
  console.error(info);
}
  • 监控网页崩溃:window 对象的 load 和 beforeunload
  • 跨域 crossOrigin 解决
原文地址:https://www.cnblogs.com/pengdt/p/12072487.html