因为浏览器大战,前端总是不断的跟各种兼容做斗争,不仅仅只是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
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="http://code.jquery.com/jquery-latest.js"></script> <title></title> </head> <body> <button id="test1">attributes获取class</button> <button id="test2">attributes检测className</button> <button id="test3">getElementById检测</button> <button id="test4">getElementsByTagName检测</button> <button id="test5">getElementsByClassName检测</button> <script type="text/javascript"> function assert(fn) { var div = document.createElement("div"); try { return !!fn(div); } catch (e) { return false; } finally { // Remove from its parent by default if (div.parentNode) { div.parentNode.removeChild(div); } // release memory in IE div = null; } } $('#test1').click(function(){ assert(function(div) { div.className = "i"; alert(div.getAttribute("class")) }); }) $('#test2').click(function(){ assert(function(div) { div.className = "i"; alert(div.getAttribute("className")) }); }) $('#test3').click(function(){ //getElementById assert(function(div) { document.body.appendChild(div).id = 'Aaron'; alert(!document.getElementsByName('Aaron').length) //IE6 false }); }) $('#test4').click(function(){ //getElementsByTagName assert(function(div) { div.appendChild(document.createComment("")); alert(div.getElementsByTagName("*").length) //ie }) }) $('#test5').click(function() { assert(function(div) { div.innerHTML = "<div class='a'></div><div class='a i'></div>"; div.firstChild.className = "i"; alert(div.getElementsByClassName("i").length === 2) }); }) //tag为*的情况,我们需要做一个兼容的处理 function byTagName(tag, context) { var elem, tmp = [], i = 0, results = context.getElementsByTagName(tag); if (tag === "*") { while ((elem = results[i++])) { if (elem.nodeType === 1) { tmp.push(elem); } } return tmp; } return results; }; //getElementsByClassName function getClassNames(tagName, classStr) { var nodes = document.getElementsByTagName(tagName), ret = []; for (i = 0; i < nodes.length; i++) { if (hasClass(nodes[i], classStr)) { ret.push(nodes[i]) } } return ret; } function hasClass(tagStr, classStr) { var arr = tagStr.className.split(/\s+/); //这个正则表达式是因为class可以有多个,判断是否包含 for (var i = 0; i < arr.length; i++) { if (arr[i] == classStr) { return true; } } return false; } </script> </body> </html>