6-3 内置方法的兼容处理
本节编程练习不计算学习进度,请电脑登录imooc.com操作

内置方法的兼容处理

因为浏览器大战,前端总是不断的跟各种兼容做斗争,不仅仅只是CSS盒子模型方面,浏览器的接口也存在各种各样的坑,看看在针对DOM的操作接口的处理中遇到兼容问题。

我直接抽取了sizzle里面的功能判断,具体的代码部分我们可以参考右侧代码:

关于属性attributes

简单来说,就是IE8之前的版本,需使用getAttribute('className')才能获得class属性的值,FF及IE8之后的版本则是W3C的标准getAttribute('class')。

这是因为IE 混淆了 DOM 对象属性(property)及 HTML 标签属性(attribute),造成了对 setAttribute、getAttribute 的不正确实现。

关于getElementById

查找元素是最常见的DOM操作,我们可以使用document对象提供的方法:

document.getElementById

取到有id的元素节点:

var div = document.getElementById("myDIV") //取到引用

这个是最常见的处理了,但是如果id是小写:

var div = document.getElementById("mydiV") //无效(IE7之前可以)

可见在IE8之前是不区分大小写的。

除此之外,如果页面有多个ID相同,也只会返回文档中第一次出现的元素。IE8之前在针对表单的处理时候,表单的name与id重名,并且name在id之前,则会返回表单元素:

<input name="aaron" value="测试">
<div id="aaron">重名</div>

此时的结果在IE7则会返回input元素,其余浏览器正常返回div元素的引用。要避免话就尽量命名不重叠。

关于getElementsByTagName

如果选择器是通配符"*"的话,IE6-8会混杂注释节点,所以针对如果是tag为*的情况,我们需要做一个兼容的处理。

byTagName

递归一下,只选取nodeType为1的元素。

getElementsByClassName

可以通过此方法获取到含有某指定class的节点集合,注意是集合,也就是此函数返回一个数组。但是,IE却并不支持这个方法,但这方法却是很有实用性,所以,我们又不得不专门为IE实现这么一个函数。

getClassNames
getClassNames

任务

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <script src="http://code.jquery.com/jquery-latest.js"></script>
  6. <title></title>
  7. </head>
  8. <body>
  9.  
  10. <button id="test1">attributes获取class</button>
  11. <button id="test2">attributes检测className</button>
  12. <button id="test3">getElementById检测</button>
  13. <button id="test4">getElementsByTagName检测</button>
  14. <button id="test5">getElementsByClassName检测</button>
  15.  
  16. <script type="text/javascript">
  17.  
  18. function assert(fn) {
  19. var div = document.createElement("div");
  20. try {
  21. return !!fn(div);
  22. } catch (e) {
  23. return false;
  24. } finally {
  25. // Remove from its parent by default
  26. if (div.parentNode) {
  27. div.parentNode.removeChild(div);
  28. }
  29. // release memory in IE
  30. div = null;
  31. }
  32. }
  33.  
  34. $('#test1').click(function(){
  35. assert(function(div) {
  36. div.className = "i";
  37. alert(div.getAttribute("class"))
  38. });
  39. })
  40.  
  41.  
  42. $('#test2').click(function(){
  43. assert(function(div) {
  44. div.className = "i";
  45. alert(div.getAttribute("className"))
  46. });
  47. })
  48.  
  49.  
  50. $('#test3').click(function(){
  51. //getElementById
  52. assert(function(div) {
  53. document.body.appendChild(div).id = 'Aaron';
  54. alert(!document.getElementsByName('Aaron').length) //IE6 false
  55. });
  56. })
  57.  
  58. $('#test4').click(function(){
  59. //getElementsByTagName
  60. assert(function(div) {
  61. div.appendChild(document.createComment(""));
  62. alert(div.getElementsByTagName("*").length) //ie
  63. })
  64. })
  65.  
  66.  
  67. $('#test5').click(function() {
  68. assert(function(div) {
  69. div.innerHTML = "<div class='a'></div><div class='a i'></div>";
  70. div.firstChild.className = "i";
  71. alert(div.getElementsByClassName("i").length === 2)
  72. });
  73. })
  74.  
  75.  
  76. //tag为*的情况,我们需要做一个兼容的处理
  77. function byTagName(tag, context) {
  78. var elem,
  79. tmp = [],
  80. i = 0,
  81. results = context.getElementsByTagName(tag);
  82. if (tag === "*") {
  83. while ((elem = results[i++])) {
  84. if (elem.nodeType === 1) {
  85. tmp.push(elem);
  86. }
  87. }
  88. return tmp;
  89. }
  90. return results;
  91. };
  92.  
  93.  
  94. //getElementsByClassName
  95. function getClassNames(tagName, classStr) {
  96. var nodes = document.getElementsByTagName(tagName),
  97. ret = [];
  98. for (i = 0; i < nodes.length; i++) {
  99. if (hasClass(nodes[i], classStr)) {
  100. ret.push(nodes[i])
  101. }
  102. }
  103. return ret;
  104. }
  105.  
  106. function hasClass(tagStr, classStr) {
  107. var arr = tagStr.className.split(/\s+/); //这个正则表达式是因为class可以有多个,判断是否包含
  108. for (var i = 0; i < arr.length; i++) {
  109. if (arr[i] == classStr) {
  110. return true;
  111. }
  112. }
  113. return false;
  114. }
  115.  
  116.  
  117.  
  118. </script>
  119.  
  120. </body>
  121. </html>
下一节