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

Tho*_*hor 4 javascript jquery

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

一个例子是jquery offset()方法.

但我也注意到jquery position()方法只有一个getter版本,并且缺少setter版本.

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

rai*_*7ow 5

这是因为,offset()position()有很大的不同,无论是通过他们的目的和引擎盖下.作者试图在文档中解释它:

.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 )
};
Run Code Online (Sandbox Code Playgroud)

(它在2.x分支中更直接,顺便说一句;不需要进行gBCR检查)


现在,position()吸气剂比较只有当目标元素有简单的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;
Run Code Online (Sandbox Code Playgroud)

然后代码计算offsetParent偏移量 - 如果是documentElement,则使用其坐标top: 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 );
Run Code Online (Sandbox Code Playgroud)

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

// 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 )
};
Run Code Online (Sandbox Code Playgroud)

而拼图的第三部分,offset()二传手.以下是关键部分:

// 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 );
Run Code Online (Sandbox Code Playgroud)

基本上,它是 - 再次 - 非常简单:计算元素的偏移量,并修改它topleft差异.复杂的部分包括position: fixedauto任何一个top或两个的值组合的情况left.


在考虑positionsetter的外观时,会出现两个问题.首先,它应该如何处理静态元素?如上所示,offsetsetter只是将它们重写positionrelative; 我们应该在这里采取相同的方式 - 并应对offsetParent突然的变化吗?

其次,每次调用setter时,都应该重新计算填充框offsetParent.当然,它在很大程度上取决于用例,但是 - 我们不应该只在元素挂载时执行此计算,并重做布局更改事件的重做吗?如果我们应该,或许offset()与现有的一起css({top, left})已经涵盖了我们所有的需求?

这些问题可能解释了为什么这个选项还没有在jQuery中实现 - 尽管它已经存在于jQuery UI中.该插件不依赖于其他jQuery UI组件,但其最新版本长约500行.

如果你认为它也应该是jQuery的一部分,那么只需在jQuery跟踪器上提出相应的问题; 至少我没有找到任何相关的东西.