(点击
上方公众号
,可快速关注)
作者:trigkit4 ( @trigkit4)
segmentfault.com/a/1190000002650240
如有好文章投稿,请点击 → 这里了解详情
js在操作DOM中存在着许多跨浏览器方面的坑,本文花了我将近一周的时间整理,我将根据实例整理那些大大小小的“坑”。
DOM的工作模式是:先加载文档的静态内容、再以动态方式对它们进行刷新,动态刷新不影响文档的静态内容。
PS:IE 中的所有 DOM 对象都是以 COM 对象的形式实现的,这意味着 IE 中的 DOM可能会和其他浏览器有一定的差异。
Node 接口
firstChild 相当于 childNodes[0];lastChild 相当于childNodes[box.childNodes.length - 1]。
nodeType返回结点的类型
--元素结点返回1
--属性结点返回2
--文本结点返回3
innerHTML 和 nodeValue
对于文本节点,nodeValue 属性包含文本。
对于属性节点,nodeValue 属性包含属性值。
nodeValue 属性对于文档节点和元素节点是不可用的。
两者区别
box
.
childNodes
[
0
].
nodeValue
=
'
abc
'
;
//结果为:
abc
abcbox
.
innerHTML
=
'
abc
'
;
//结果为:abc
nodeName属性获得结点名称
--对于元素结点返回的是标记名称,如:
返回的是"a"
--对于属性结点返回的是属性名称,如:class="test" 返回的是test
--对于文本结点返回的是文本的内容
tagName
document.getElementByTagName(tagName):返回一个数组,包含对这些结点的引用
getElementsByTagName()方法将返回一个对象数组 HTMLCollection(NodeList),这个数组保存着所有相同元素名的节点列表。
document.getElementsByTagName('*');//获取所有元素
PS:IE 浏览器在使用通配符的时候,会把文档最开始的 html 的规范声明当作第一个元素节点。
document
.
getElementsByTagName
(
'li'
);
//获取所有 li 元素,返回数组
document
.
getElementsByTagName
(
'li'
)[
0
];
//获取第一个 li 元素,HTMLLIElement
document
.
getElementsByTagName
(
'li'
).
item
(
0
);
//获取第一个 li 元素,HTMLLIElement
document
.
getElementsByTagName
(
'li'
).
length
;
//获取所有 li 元素的数目
节点的绝对引用:
返回文档的根节点:document.documentElement
返回当前文档中被击活的标签节点:document.activeElement
返回鼠标移出的源节点:event.fromElement
返回鼠标移入的源节点:event.toElement
返回激活事件的源节点:event.srcElement
节点的相对引用:(设当前对节点为node)
返回父节点:node.parentNode || node.parentElement(IE)
返回子节点集合(包含文本节点及标签节点):node.childNodes
返回子标签节点集合:node.children
返回子文本节点集合:node.textNodes
返回第一个子节点:node.firstChild
返回最后一个子节点:node.lastChild
返回同属下一个节点:node.nextSibling
返回同属上一个节点:node.previousSibling
节点信息
是否包含某节点:node.contains()
是否有子节点node.hasChildNodes()
创建新节点
createDocumentFragment()--创建文档碎片节点
createElement(tagname)--创建标签名为tagname的元素
createTextNode(text)--创建包含文本text的文本节点
获取鼠标点击事件的位置
以下所描述的属性在chrome和Safari 都很给力的支持了。
问题一:Firefox,Chrome、Safari和IE9都是通过非标准事件的pageX和pageY属性来获取web页面的鼠标位置的。pageX/Y获取到的是触发点相对文档区域左上角距离,以页面为参考点,不随滑动条移动而变化
问题二:在IE 中,event 对象有 x, y 属性(事件发生的位置的 x 坐标和 y 坐标)火狐中没有。在火狐中,与event.x 等效的是event.pageX。event.clientX 与 event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。
offsetX:IE特有,chrome也支持。鼠标相比较于触发事件的元素的位置,以元素盒子模型的内容区域的左上角为参考点,如果有boder,可能出现负值
问题三:
scrollTop为滚动条向下移动的距离,所有浏览器都支持document.documentElement。
其余参照:http://segmentfault.com/a/1190000002559158#articleHeader11
参照表
(+为支持,-为不支持):
offsetX
/
offsetY
:
W3C
-
IE
+
Firefox
-
Opera
+
Safari
+
chrome
+
x
/
y
:
W3C
-
IE
+
Firefox
-
Opera
+
Safari
+
chrome
+
layerX
/
layerY
:
W3C
-
IE
-
Firefox
+
Opera
-
Safari
+
chrome
+
pageX
/
pageY
:
W3C
-
IE
-
Firefox
+
Opera
+
Safari
+
chrome
+
clientX
/
clientY
:
W3C
+
IE
+
Firefox
+
Opera
+
Safari
+
chrome
+
screenX
/
screenY
:
W3C
+
IE
+
Firefox
+
Opera
+
Safari
+
chrome
+
查看下方DEMO:
你会发现offsetX在Firefox下是undefined,在chrome和IE则会正常显示。
https://jsfiddle.net/f4am208m/embedded/result/
offsetLeft和style.left区别
1.style.left返回的是字符串,比如10px。而offsetLeft返回的是数值,比如数值10
2.style.left是可读写的,offsetLeft是只读的
3.style.left的值需要事先定义(在样式表中定义无效,只能取到在html中定义的值),否则取到的值是空的
getComputedStyle与currentStyle
getComputedStyle()接受两个参数:要取得计算样式的元素和一个伪元素,如果不需要伪元素,则可以是null。然而,在IE中,并不支持getComputedStyle,IE提供了currentStyle属性。
getComputedStyle(obj , false ) 是支持 w3c (FF12、chrome 14、safari):在FF新版本中只需要第一个参数,即操作对象,第二个参数写“false”也是大家通用的写法,目的是为了兼容老版本的火狐浏览器。
缺点:在标准浏览器中正常,但在IE6/7/8中不支持
window
.
onload
=
function
(){
var
oBtn
=
document
.
getElementById
(
'btn'
);
var
oDiv
=
document
.
getElementById
(
'div1'
);
oBtn
.
onclick
=
function
(){
//alert(oDiv.style.width); //写在样式表里无法读取,只能得到写在行内的
//alert(getComputedStyle(oDiv).width); //适用于标准浏览器 IE6、7、8不识别
//alert(oDiv.currentStyle.width); //适用于IE浏览器,标准浏览器不识别
if
(
oDiv
.
currentStyle
){
alert
(
oDiv
.
currentStyle
.
width
);
}
else
{
alert
(
getComputedStyle
(
oDiv
).
width
);
}
};
};
取消表单提交
"on" + event;
eventObj.attachEvent(event,eventHandler);
}else{
eventObj["on" + event] = eventHandler;
}
}
function cancelEvent(event){
if(event.preventDefault){
event.preventDefault();//w3c
}else{
event.returnValue = true;//IE
}
}
window.onload = function () {
var form = document.forms["picker"];
listenEvent(form,"submit",validateFields);
};
function validateFields(evt){
evt = evt ? evt : window.event;
...
if(invalid){
cancelEvent(evt);
}
}
确定浏览器窗口的尺寸
对于主流浏览器来说,比如IE9、Firefox,Chrome和Safari,支持名为innerWidth 和 innerHeight的窗口对象属性,它返回窗口的视口区域,减去任何滚动条的大小。IE不支持innerWidth 和 innerHeight
.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight);
}else{
w = window.innerWidth;
h = window.innerHeight;
}
return {width:w,height:h};
}
console.log(size());//Object { width: 1366, height: 633 }
实用的 JavaScript 方案(涵盖所有浏览器):
var
w
=
window
.
innerWidth
||
document
.
documentElement
.
clientWidth
||
document
.
body
.
clientWidth
;
var
h
=
window
.
innerHeight
||
document
.
documentElement
.
clientHeight
||
document
.
body
.
clientHeight
;
对于 IE 6、7、8的方案如下:
document
.
documentElement
.
clientHeight
document
.
documentElement
.
clientWidth
或者
document
.
body
.
clientHeight
document
.
body
.
clientWidth
Document对象的body属性对应HTML文档的
标签。Document对象的documentElement属性则表示 HTML文档的根节点。
attributes 属性
attributes 属性返回该节点的属性节点集合。
document
.
getElementById
(
'box'
).
attributes
//NamedNodeMap
document
.
getElementById
(
'box'
).
attributes
.
length
;
//返回属性节点个数
document
.
getElementById
(
'box'
).
attributes
[
0
];
//Attr,返回最后一个属性节点
document
.
getElementById
(
'box'
).
attributes
[
0
].
nodeType
;
//2,节点类型
document
.
getElementById
(
'box'
).
attributes
[
0
].
nodeValue
;
//属性值
document
.
getElementById
(
'box'
).
attributes
[
'id'
];
//Attr,返回属性为 id 的节点
document
.
getElementById
(
'box'
).
attributes
.
getNamedItem
(
'id'
);
//Attr
setAttribute 和 getAttribute
在IE中是不认识class属性的,需改为className属性,同样,在Firefox中,也是不认识className属性的,Firefox只认识class属性,所以通常做法如下:
element
.
setAttribute
(
class
,
value
);
//for firefox
element
.
setAttribute
(
className
,
value
);
//for IE
IE:可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性
Firefox:只能使用getAttribute()获取自定义属性.
解决方法:统一通过getAttribute()获取自定义属性
document
.
getElementById
(
'box'
).
getAttribute
(
'id'
);
//获取元素的 id 值
document
.
getElementById
(
'box'
).
id
;
//获取元素的 id 值
document
.
getElementById
(
'box'
).
getAttribute
(
'mydiv'
);
//获取元素的自定义属性值
document
.
getElementById
(
'box'
).
mydiv
//获取元素的自定义属性值, IE 不支持非
document
.
getElementById
(
'box'
).
getAttribute
(
'class'
);
//获取元素的 class 值,IE 不支持
document
.
getElementById
(
'box'
).
getAttribute
(
'className'
);
//非 IE 不支持
PS:在 IE7 及更低版本的IE浏览器中,使用 setAttribute()方法设置 class 和 style 属性是没有效果的,虽然 IE8 解决了这个bug,但还是不建议使用。
removeAttribute()方法
removeAttribute
()
可以移除
HTML
属性。
document
.
getElementById
(
'box'
).
removeAttribute
(
'style'
);
//移除属性
PS:IE6 及更低版本不支持 removeAttribute()方法。
跨浏览器事件Event对象