浅析JavaScript中浏览器的兼容问题


Posted in Javascript onApril 19, 2016

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

1、innerText 和 innerContent
1)innerText 和 innerContent 的作用相同
2)innerText IE8之前的浏览器支持
3)innerContent 老版本的Firefox支持
4)新版本的浏览器两种方式都支持

1 // 老版本浏览器兼容 innerText 和 innerContent
2 if (element.textContent) {
3    return element.textContent ;
4  } else {
5    return element.innerText;
6  }

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

        ①previousElementSibling 获取上一个紧邻的兄弟元素,会忽略空白 
        ②nextElementSibling  获取下一个紧邻的兄弟元素,会忽略空白

//兼容浏览器
// 获取下一个紧邻的兄弟元素
function getNextElement(element) {
  // 能力检测
 if(element.nextElementSibling) {
   return element.nextElementSibling;
  } else {
     var node = element.nextSibling;
     while(node && node.nodeType !== 1) {
         node = node.nextibling;
     }
     return node;
  }
 }
/**
* 返回上一个元素
* @param element
* @returns {*}
*/
function getPreviousElement(element) {
  if(element.previousElementSibling) {
    return element.previousElementSibling;
  }else {
    var el = element.previousSibling;
    while(el && el.nodeType !== 1) {
      el = el.previousSibling;
      }
    return el;
  }
}
/**
* 返回第一个元素firstElementChild的浏览器兼容
* @param parent
* @returns {*}
*/
function getFirstElement(parent) {
  if(parent.firstElementChild) {
    return parent.firstElementChild;
  }else {
    var el = parent.firstChild;
    while(el && el.nodeType !== 1) {
      el = el.nextSibling;
      }
    return el;
  }
}
/**
* 返回最后一个元素
* @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();  
 // 使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组

// 兼容旧环境
if (!Array.prototype.filter)
{
 Array.prototype.filter = function(fun /*, thisArg */)
 {
  "use strict";
  if (this === void 0 || this === null)
   throw new TypeError();
  var t = Object(this);
  var len = t.length >>> 0;
  if (typeof fun !== "function")
   throw new TypeError();
  var res = [];
  var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
  for (var i = 0; i < len; i++)
  {
   if (i in t)
   {
    var val = t[i];
    // NOTE: Technically this should Object.defineProperty at
    //    the next index, as push can be affected by
    //    properties on Object.prototype and Array.prototype.
    //    But that method's new, and collisions should be
    //    rare, so use the more-compatible alternative.
    if (fun.call(thisArg, val, i, t))
     res.push(val);
   }
  }
  return res;
 };
}

4、array.forEach();
// 遍历数组

//兼容旧环境
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {
 Array.prototype.forEach = function(callback, thisArg) {
  var T, k;
  if (this == null) {
   throw new TypeError(' this is null or not defined');
  }
  // 1. Let O be the result of calling toObject() passing the
  // |this| value as the argument.
  var O = Object(this);
  // 2. Let lenValue be the result of calling the Get() internal
  // method of O with the argument "length".
  // 3. Let len be toUint32(lenValue).
  var len = O.length >>> 0;
  // 4. If isCallable(callback) is false, throw a TypeError
  exception. // See: http://es5.github.com/#x9.11
  if (typeof callback !== "function") {
   throw new TypeError(callback + ' is not a function');
  }
  // 5. If thisArg was supplied, let T be thisArg; else let
  // T be undefined.
  if (arguments.length > 1) {
   T = thisArg;
  }
  // 6. Let k be 0
  k = 0;
  // 7. Repeat, while k < len
  while (k < len) {
   var kValue;
   // a. Let Pk be ToString(k).
   //  This is implicit for LHS operands of the in operator
   // b. Let kPresent be the result of calling the HasProperty
   //  internal method of O with argument Pk.
   //  This step can be combined with c
   // c. If kPresent is true, then
   if (k in O) {
    // i. Let kValue be the result of calling the Get internal
    // method of O with argument Pk.
    kValue = O[k];
    // ii. Call the Call internal method of callback with T as
    // the this value and argument list containing kValue, k, and O.
    callback.call(T, kValue, k, O);
   }
   // d. Increase k by 1.
   k++;
  }
  // 8. return undefined
 };
}

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

var EventTools = {
    addEventListener: function (element, eventName, listener) {
      //能力检测
      if(element.addEventListener) {
        element.addEventListener(eventName, listener,false);
      }else if(element.attachEvent) {
        element.attachEvent("on" + eventName, listener);
      }else{
        element["on" + eventName] = listener;
      }
    },

//  想要移除事件,不能使用匿名函数
    removeEventListener: function (element, eventName, listener) {
      if(element.removeEventListener) {
        element.removeEventListener(eventName,listener,false);
      }else if(element.detachEvent) { //IE8以前注册.attachEvent和移除事件.detachEvent
        element.detachEvent("on"+eventName,listener);
      }else{
        element["on" + eventName] = null;
      }
    }
  };

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;

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

7、获取鼠标在页面上的位置
①在可视区域中的位置:  e.clientX   e.clientY
②在文档中的位置:
        i) e.pageX      e.pageY
        ii)浏览器兼容

var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
 var pageY = e.clientY + scrollTop;

8、获取页面滚动的距离

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

9、取消文本的选择

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

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

以上这篇浅析JavaScript中浏览器的兼容问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javaScript函数中执行C#代码中的函数方法总结
Aug 07 Javascript
基于jQuery的Web上传插件Uploadify使用示例
May 19 Javascript
JS表格组件神器bootstrap table详解(强化版)
May 26 Javascript
JavaScript Promise 用法
Jun 14 Javascript
js自定义Tab选项卡效果
Jun 05 Javascript
vue引入ueditor及node后台配置详解
Jan 03 Javascript
基于mpvue小程序使用echarts画折线图的方法示例
Apr 24 Javascript
用js简单提供增删改查接口
May 12 Javascript
Vue模板语法中数据绑定的实例代码
May 17 Javascript
javascript中的数据类型检测方法详解
Aug 07 Javascript
JavaScript相等运算符的九条规则示例详解
Oct 20 Javascript
vue-cli+webpack项目打包到服务器后,ttf字体找不到的解决操作
Aug 28 Javascript
javascript+HTML5 Canvas绘制转盘抽奖
May 16 #Javascript
深入浅析JavaScript中的constructor
Apr 19 #Javascript
js点击返回跳转到指定页面实现过程
Aug 20 #Javascript
javascript html5摇一摇功能的实现
Apr 19 #Javascript
一些实用性较高的js方法
Apr 19 #Javascript
jQuery移动端日期(datedropper)和时间(timedropper)选择器附源码下载
Apr 19 #Javascript
JavaScript中创建对象的模式汇总
Apr 19 #Javascript
You might like
新手学习PHP的一些基础知识分享
2011/07/27 PHP
php实现分页工具类分享
2014/01/09 PHP
PHP异常处理定义与使用方法分析
2017/07/25 PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
2017/10/25 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
JQuery Ajax通过Handler访问外部XML数据的代码
2010/06/01 Javascript
onkeypress字符按键兼容所有浏览器使用介绍
2013/04/24 Javascript
JS保存和删除cookie操作 判断cookie是否存在
2013/11/13 Javascript
JavaScript职责链模式概述
2016/09/17 Javascript
JavaScript实现的商品抢购倒计时功能示例
2017/04/17 Javascript
开发Vue树形组件的示例代码
2017/12/21 Javascript
node实现mock-plugin中间件的方法
2019/12/25 Javascript
nodejs开发一个最简单的web服务器实例讲解
2020/01/02 NodeJs
Vue页面手动刷新,实现导航栏激活项还原到初始状态
2020/08/06 Javascript
vue+iview实现文件上传
2020/11/17 Vue.js
python以环状形式组合排列图片并输出的方法
2015/03/17 Python
Python的math模块中的常用数学函数整理
2016/02/04 Python
python魔法方法-属性访问控制详解
2016/07/25 Python
浅谈python中copy和deepcopy中的区别
2017/10/23 Python
Python列表生成式与生成器操作示例
2018/08/01 Python
只需7行Python代码玩转微信自动聊天
2019/01/27 Python
Python面向对象程序设计之私有属性及私有方法示例
2019/04/08 Python
基于pycharm 项目和项目文件命名规则的介绍
2021/01/15 Python
anaconda升级sklearn版本的实现方法
2021/02/22 Python
使用CSS3创建动态菜单效果
2015/07/10 HTML / CSS
加拿大著名时装品牌:SOIA & KYO
2016/08/23 全球购物
玖熙女鞋美国官网:Nine West
2016/10/06 全球购物
电影T恤、80年代T恤和80年代服装:TV Store Online
2020/01/05 全球购物
大学生自荐信
2013/12/11 职场文书
教师工作决心书
2015/02/04 职场文书
2015年环卫工作总结
2015/04/28 职场文书
学生乘坐校车安全责任书
2015/05/11 职场文书
MySQL CHAR和VARCHAR该如何选择
2021/05/31 MySQL
浅谈哪个Python库才最适合做数据可视化
2021/06/28 Python
Win11无法访问设备和打印机 如何解决页面空白
2022/04/09 数码科技
CSS中理解层叠性及权重如何分配
2022/12/24 HTML / CSS