为什么jquery position()方法没有setter版本

时间:2018-04-11 04:02:03

标签: javascript jquery

我目前正在研究jquery并注意到jquery中的大多数方法都有一个设置和getter版本。即该方法用作setter或getter,具体取决于传递给方法的参数的类型/数量。

一个例子是http://yourserver:port/_cat/thread_pool

但是我也注意到jquery offset() method只有一个getter版本,并且它的setter版本丢失了。

有没有人知道为什么position()方法没有setter版本?我不完全确定,但我认为在某些情况下,setter版本会很有用。

1 个答案:

答案 0 :(得分:5)

这是因为offset()position()在目的和内在上都大不相同。作者试图在the docs中进行解释:

  

.position()方法使我们能够检索的当前位置   元素(特别是其边距框)相对于偏移父级   (特别是其填充框,其中不包括边距和边框)。   将其与.offset()进行对比,后者可检索当前位置   相对于文档

但是,最好的解释是像往常一样在源中。 offset() getter非常简单:检查元素在实时DOM中的存在之后,将其框与文档的框进行比较,然后滚动调整:

// If we don't have gBCR, just use 0,0 rather than error
// BlackBerry 5, iOS 3 (original iPhone)
if ( typeof elem.getBoundingClientRect !== "undefined" ) {
    box = elem.getBoundingClientRect();
}
win = getWindow( doc );
return {
    top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0),
    left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
};

(在2.x分支中更直接,顺便说一句;无需gBCR检查)


现在,position() getter仅在目标元素已应用position: fixed相对简单-只需获取gBCR结果作为偏移量即可。

否则,事情会变得混乱。首先,算法应定位“真实” offsetParent-位置最接近的前任而不是静态。如果未找到,则使用documentElement

// key part of `offsetParent()` method
while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) &&
       jQuery.css( offsetParent, "position" ) === "static" ) ) {
    offsetParent = offsetParent.offsetParent;
}
return offsetParent || documentElement;

然后代码计算offsetParent偏移量-如果使用documentElementtop: 0, left: 0则使用其坐标。而且不要忘记边界!

var parentOffset = { top: 0, left: 0 },
// ... later on
if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
    parentOffset = offsetParent.offset();
}
// Add offsetParent borders
parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );

最后,比较偏移量-现在还考虑了元素的边距:

// Subtract parent offsets and element margins
// note: when an element has margin: auto the offsetLeft and marginLeft
// are the same in Safari causing offset.left to incorrectly be 0
return {
    top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
    left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
};

难题的第三部分,offset() setter。以下是关键部分:

// set position first, in-case top/left are set even on static elem
if ( position === "static" ) {
    elem.style.position = "relative";
}

curOffset = curElem.offset();
curCSSTop = jQuery.css( elem, "top" );
curCSSLeft = jQuery.css( elem, "left" );
calculatePosition = ( position === "absolute" || position === "fixed" ) &&
        jQuery.inArray( "auto", [ curCSSTop, curCSSLeft ] ) > -1;

// need to be able to calculate position if either top or left
// is auto and position is either absolute or fixed
if ( calculatePosition ) {
    curPosition = curElem.position();
    curTop = curPosition.top;
    curLeft = curPosition.left;
} else {
    curTop = parseFloat( curCSSTop ) || 0;
    curLeft = parseFloat( curCSSLeft ) || 0;
}

// ...
if ( options.top != null ) {
    props.top = ( options.top - curOffset.top ) + curTop;
}
if ( options.left != null ) {
    props.left = ( options.left - curOffset.left ) + curLeft;
}
// ...
curElem.css( props );

从本质上讲,这又非常简单:计算元素的偏移量,并通过差异来修改其topleft。复杂的部分涵盖position: fixedautotop的{​​{1}}值组合的情况。


在思考left设置器的外观时,会出现两个问题。 首先,静态元素应该怎么做?如上所示,position设置器仅将其offset重写为position;我们在这里应该采取相同的方式-处理relative的突然变化吗?

第二,每次调用setter时,都应重新计算offsetParent的填充框。当然,它在很大程度上取决于用例,但是-我们不应该仅在元素挂载并重做布局更改事件时才进行此计算吗?如果我们应该,offsetParent的二传手与现有的offset()一起已经满足了我们的所有需求?

这些问题可能解释了为什么该选项尚未在jQuery中实现-尽管jQuery UI中已经存在该选项。该插件不依赖于其他jQuery UI组件,但是its latest version长约500行。

如果您确实认为它也应该是jQuery的一部分,则只需在jQuery跟踪器上提出一个相应的问题即可;至少我还没有找到anything related