DOM之parentNode与offsetParent
DOM中有两个属性parentNode和offsetParent,想必区别大家都是知道的,可用法上还是有一些需要注意的地方,尤其是后者,想知道吗?继续往下看咯。
parentNode指的是父节点,element.parentNode,获取某一个元素的父节点,这里的父节点呢,只有一个,就是指的是最临近的直接父节点。比如我们经常会有这样的需求:一个列表,点击删除删除一列,如下:
<ul id="list"> <li>我是沐晴<span>删除</span></li> <li>我是沐晴<span>删除</span></li> <li>我是沐晴<span>删除</span></li> </ul> var oList = document.getElementById("list"); var aSpan = oList.getElementsByTagName("span"); for(var i=0;i<aSpan.length;i++){ aSpan[i].onclick = function(){ this.parentNode.style.display = "none"; } }
例子很简单,点击让对应的父元素隐藏即可。来看下一个属性.
offsetParent 这里的父节点,指的是相对于父节点,也就是说某个元素相对于谁定位,谁就是他的父亲。
和它很相似的属性还有offsetLeft \ offsetTop ,他们指的是前元素到offsetParent的距离。
不过不同的浏览器对于这个属性的解释也是有一些不同的:(什么时候元素会相对于别人定位呢,其实也就是有父元素设置相对定位,绝对定位的时候(relative,absolute),这个父元素就叫做定位父级,这个大家应该都懂。)
其他浏览器下:
当没有定位父级的时候: offsetParent 指的是body
有定位父级的时候:offsetParent 指的就是定位父级
IE7以下:
当没有定位父级的时候又分两种情况:
如果自己没有定位: offsetParent 指的是body
如果自己有定位:offsetLeft 指的是 html
如果有定位父级:
如果自己没有定位: offsetParent 指的是body
如果自己有定位:offsetLeft 指的是 定位父级
ie7以下,如果当前元素的某个父级触发了layout,那么offsetParent就会被指向到这个触发了layout特性的父节点上
所以我们在写代码的时候是需要注意这些细节的,我们在写代码的时候经常有这样的需求,获取一个元素到浏览器的距离,一般情况我们是会用到offsetLeft \ offsetTop ,但是这只适用于页面没有定位父级的时候,当我们的代码很多的时候,其中有些元素可能被设置了定位的时候,这个值很可能就不准了。那么如何能完全准确的获取到元素到文档的距离呢?
下面来看张图:
求diiv1到文档的距离,灰色的框是文档,其中又有相对定位父级2和3,这个时候我们怎么求div1到文档的距离呢?通过观察,我们可以知道到文档的距离,正好等于div1到它的定位父级div2的距离加上div2到它的定位父级div3的距离,再加上div3到文档的距离,也就是图中的1+2+3;所以我们可以先求出这个元素到自己的定位父级2的距离,然后再求出它的定位父级2到自己定位父级3的距离。依次到最后就会求得最终的到文档的距离。(body的offsetParent不存在)
我们可以总结出这样的代码
// obj是一个载体,用来放每个定位父级,是在改变的,比如上面的那张图来看,一开始它是div1,当计算出div1到div2的距离的时候,再把它变成div2,再求div2到定位父级div3的距离。依次循环到最后没有定位父级了,它就变成null了,然后停止了循环 var left = 0; while (obj) { // 当这个元素节点存在的时候循环下面的代码 left += obj.offsetLeft; // 把每个元素定位父级的距离都累加起来 obj = obj.offsetParent; // 把当前的元素赋给obj }
为了也能求出竖直方向上到文档的距离,也为了更方便,我们可以封装成一个函数:
function getPos(obj) { var pos = {left:0, top:0}; while (obj) { pos.left += obj.offsetLeft; pos.top += obj.offsetTop; obj = obj.offsetParent; } return pos; }
这个函数会经常用到,像我们的瀑布流中,也是需求的。
最后添加个笔记:
offsetWidth \ clientWidth
style.width : width(样式宽 带单位)
clientWidth : width+padding(不带单位 可视区宽)
offsetWidth:width+padding+border (占位置宽)
好啦,希望今天的分享能带给大家新的体会。