你的位置:首页 > Java教程

[Java教程]JavaScript中浏览器兼容问题


  浏览器兼容性问题是在实际开发中容易忽略而又最重要的一部分。我们在讲老版本浏览器兼容问题之前,首先要了解什么是能力检测,它是来检测浏览器有没有这种能力,即判断当前浏览器是否支持要调用的属性或者方法。下面做了一些简短的介绍。

1、innerText 和 innerContent

1)innerText 和 innerContent 的作用相同
2)innerText IE8之前的浏览器支持
3)innerContent 老版本的Firefox支持
4)新版本的浏览器两种方式都支持
1 // 老版本浏览器兼容 innerText 和 innerContent2 if (element.textContent) {3    return element.textContent ;4  } else {5    return element.innerText;6  }

2、获取兄弟节点/元素的兼容性问题


 1)兄弟节点,所有浏览器都支持
        ①nextSibling 下一个兄弟节点,可能是非元素节点;会获取到文本节点
        ②previousSibling  上一个兄弟节点,可能是非元素节点;会获取到文本节点
 2)兄弟元素,IE8以前不支持

        ①previousElementSibling 获取上一个紧邻的兄弟元素,会忽略空白 
        ②nextElementSibling  获取下一个紧邻的兄弟元素,会忽略空白    
  //兼容浏览器
1 // 获取下一个紧邻的兄弟元素 2 function getNextElement(element) { 3 // 能力检测 4 if(element.nextElementSibling) { 5 return element.nextElementSibling; 6 } else { 7 var node = element.nextSibling; 8 while(node && node.nodeType !== 1) { 9 node = node.nextibling;10 }11 return node;12 }13 }


 1 /** 2 * 返回上一个元素 3 * @param element 4 * @returns {*} 5 */ 6 function getPreviousElement(element) { 7   if(element.previousElementSibling) { 8     return element.previousElementSibling; 9   }else {10     var el = element.previousSibling;11     while(el && el.nodeType !== 1) {12       el = el.previousSibling;13       }14     return el;15   }16 }

 1 /** 2 * 返回第一个元素firstElementChild的浏览器兼容 3 * @param parent 4 * @returns {*} 5 */ 6 function getFirstElement(parent) { 7   if(parent.firstElementChild) { 8     return parent.firstElementChild; 9   }else {10     var el = parent.firstChild;11     while(el && el.nodeType !== 1) {12       el = el.nextSibling;13       }14     return el;15   }16 }


/*** 返回最后一个元素* @param parent* @returns {*}*/function getLastElement(parent) {  if(parent.lastElementChild) {    return parent.lastElementChild;  }else {    var el = parent.lastChild;    while(el && el.nodeType !== 1) {      el = el.previousSibling;      }    return el;  }}

/***获取当前元素的所有兄弟元素* @param element* @returns {Array}*/function sibling(element) {  if(!element) return ;    var elements = [ ];  var el = element.previousSibling;  while(el) {    if(el.nodeType === 1) {      elements.push(el);    }    el = el.previousSibling;  }   el = element.previousSibling;   while(el ) {    if(el.nodeType === 1) {      elements.push(el);    }    el = el.nextSibling;  }    return elements;}

3、array.filter();   

 // 使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组

 1 // 兼容旧环境 2 if (!Array.prototype.filter) 3 { 4  Array.prototype.filter = function(fun /*, thisArg */) 5  { 6   "use strict"; 7   if (this === void 0 || this === null) 8    throw new TypeError(); 9   var t = Object(this);10   var len = t.length >>> 0;11   if (typeof fun !== "function")12    throw new TypeError();13   var res = [];14   var thisArg = arguments.length >= 2 ? arguments[1] : void 0;15   for (var i = 0; i < len; i++)16   {17    if (i in t)18    {19     var val = t[i];20     // NOTE: Technically this should Object.defineProperty at21     //    the next index, as push can be affected by22     //    properties on Object.prototype and Array.prototype.23     //    But that method's new, and collisions should be24     //    rare, so use the more-compatible alternative.25     if (fun.call(thisArg, val, i, t))26      res.push(val);27    }28   }29   return res;30  };31 }

4、array.forEach();

// 遍历数组

 1 //兼容旧环境 2 // Production steps of ECMA-262, Edition 5, 15.4.4.18 3 // Reference: http://es5.github.io/#x15.4.4.18 4 if (!Array.prototype.forEach) { 5  Array.prototype.forEach = function(callback, thisArg) { 6   var T, k; 7   if (this == null) { 8    throw new TypeError(' this is null or not defined'); 9   }10   // 1. Let O be the result of calling toObject() passing the11   // |this| value as the argument.12   var O = Object(this);13   // 2. Let lenValue be the result of calling the Get() internal14   // method of O with the argument "length".15   // 3. Let len be toUint32(lenValue).16   var len = O.length >>> 0;17   // 4. If isCallable(callback) is false, throw a TypeError18   exception. // See: http://es5.github.com/#x9.1119   if (typeof callback !== "function") {20    throw new TypeError(callback + ' is not a function');21   }22   // 5. If thisArg was supplied, let T be thisArg; else let23   // T be undefined.24   if (arguments.length > 1) {25    T = thisArg;26   }27   // 6. Let k be 028   k = 0;29   // 7. Repeat, while k < len30   while (k < len) {31    var kValue;32    // a. Let Pk be ToString(k).33    //  This is implicit for LHS operands of the in operator34    // b. Let kPresent be the result of calling the HasProperty35    //  internal method of O with argument Pk.36    //  This step can be combined with c37    // c. If kPresent is true, then38    if (k in O) {39     // i. Let kValue be the result of calling the Get internal40     // method of O with argument Pk.41     kValue = O[k];42     // ii. Call the Call internal method of callback with T as43     // the this value and argument list containing kValue, k, and O.44     callback.call(T, kValue, k, O);45    }46    // d. Increase k by 1.47    k++;48   }49   // 8. return undefined50  };51 }

5、注册事件

 .addEventListener = function (type,listener,useCapture ) { };//第一个参数 事件名称//第二个参数 事件处理函数(监听者)//第三个参数 true捕获 false冒泡//IE9以后才支持

// 兼容旧环境

 1 var EventTools = { 2     addEventListener: function (element, eventName, listener) { 3       //能力检测 4       if(element.addEventListener) { 5         element.addEventListener(eventName, listener,false); 6       }else if(element.attachEvent) { 7         element.attachEvent("on" + eventName, listener); 8       }else{ 9         element["on" + eventName] = listener;10       }11     },12 13 //  想要移除事件,不能使用匿名函数14     removeEventListener: function (element, eventName, listener) {15       if(element.removeEventListener) {16         element.removeEventListener(eventName,listener,false);17       }else if(element.detachEvent) { //IE8以前注册.attachEvent和移除事件.detachEvent18         element.detachEvent("on"+eventName,listener);19       }else{20         element["on" + eventName] = null;21       }22     }23   };

6、事件对象

 1)事件参数e,就是事件对象,标准的获取方式
btn.onclick = function(e) { }



 2)e.eventPhase 事件阶段,IE8以前不支持
 3)e.target 始终是触发事件的对象(点击的按钮)
        i)IE8以前 srcElement
        ii)浏览器兼容
var target = e.target || window.event.srcElement;



1 // 获取事件对象 兼容浏览器2 getEvent: function(e) {3   return e || window.event; // e事件对象 标准的获取方式; window.event IE8以前获取事件对象的方式4  }5 // 兼容target6 getTarget: function(e) {7   return e.target || e.srcElement;8 }

7、获取鼠标在页面上的位置

①在可视区域中的位置:  e.clientX   e.clientY
②在文档中的位置: 
        i) e.pageX      e.pageY
        ii)浏览器兼容
1 var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;2 var pageY = e.clientY + scrollTop;

8、获取页面滚动的距离

1 // 兼容浏览器2 var scrollTop = document.documentElement.scrollTop || document.body.scrolltop;









9、取消文本的选择

1 // 兼容浏览器2 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

  

【总结】这里只是做了一部分的小结,实际开发中也还会遇到各种浏览器兼容的问题。不同浏览器在PC端和手机端也会遇到不同适配问题,这些就有待童鞋们一起去发掘总结啦~~希望能帮到大家,不足的地方请多指教啦~~~