不使用jQuery复制$('body').outerHeight(true)的效果

4
我有一些页面加载到父页面的iframe中,我使用postMessage将子页面的高度发送到父级,以便它可以调整iframe的大小。子页面非常简单,使用jQuery只是为了找到body的高度似乎有些浪费。然而,我尝试使用纯JavaScript来复制上述调用的效果,但至今未能成功。
我尝试过将scrollHeight、offsetHeight和clientHeight应用于body和body.documentElement,但是它们都不匹配。在不同的浏览器中它们差异很大,特别是在切换不同大小的子文档时。以下是所有子页面的onload事件处理程序的实际代码:
window.onload = function() {
    alert("height(1) = " + document.body.scrollHeight + "\n" +
        "height(2) = " + document.documentElement.scrollHeight + "\n" +
        "height(3) = " + document.body.offsetHeight + "\n" +
        "height(4) = " + document.documentElement.offsetHeight + "\n" +
        "height(5) = " + document.body.clientHeight + "\n" +
        "height(6) = " + document.documentElement.clientHeight + "\n" +
        "height(7) = " + $('body').outerHeight(true)
    );
    parent.postMessage($('body').outerHeight(true) + "px", "*");
}

在每个浏览器(IE8 / FF / Chrome)的每种情况下,前六个值都与第七个值不匹配。第二个值最接近,但在从一个大的子页面切换到较小的页面时,在Chrome中失败 - 它仍然给出先前页面的大小。

我确实阅读了jQuery的源代码,但我的JavaScript水平还不够好,无法弄清楚它在做什么。

4个回答

0

接着jQuery进入cssHooks函数,一切开始变得复杂。反思后,花时间去弄清它在做什么似乎是毫无意义的;我应该直接使用它。我在父页面中使用它,所以所有浏览器都已经缓存了它。


0

Vanilla Masonry有一个函数 - getWH() - 从Jquery重构而来,应该可以满足您的需求: https://github.com/desandro/vanilla-masonry

// returns width/height of element, refactored getWH from jQuery
function getWH( elem, measure, isOuter ) {
    // Start with offset property
    var isWidth = measure !== 'height',
        val = isWidth ? elem.offsetWidth : elem.offsetHeight,
        dirA = isWidth ? 'Left' : 'Top',
        dirB = isWidth ? 'Right' : 'Bottom',
        computedStyle = getStyle( elem ),
        paddingA = parseFloat( computedStyle[ 'padding' + dirA ] ) || 0,
        paddingB = parseFloat( computedStyle[ 'padding' + dirB ] ) || 0,
        borderA = parseFloat( computedStyle[ 'border' + dirA + 'Width' ] ) || 0,
        borderB = parseFloat( computedStyle[ 'border' + dirB + 'Width' ] ) || 0,
        computedMarginA = computedStyle[ 'margin' + dirA ],
        computedMarginB = computedStyle[ 'margin' + dirB ],
        marginA, marginB;

    if ( !supportsPercentMargin ) {
        computedMarginA = hackPercentMargin( elem, computedStyle, computedMarginA );
        computedMarginB = hackPercentMargin( elem, computedStyle, computedMarginB );
    }

    marginA = parseFloat( computedMarginA ) || 0;
    marginB = parseFloat( computedMarginB ) || 0;

    if ( val > 0 ) {

        if ( isOuter ) {
            // outerWidth, outerHeight, add margin
            val += marginA + marginB;
        } else {
            // like getting width() or height(), no padding or border
            val -= paddingA + paddingB + borderA + borderB;
        }

    } else {

        // Fall back to computed then uncomputed css if necessary
        val = computedStyle[ measure ];
        if ( val < 0 || val === null ) {
            val = elem.style[ measure ] || 0;
        }
        // Normalize "", auto, and prepare for extra
        val = parseFloat( val ) || 0;

        if ( isOuter ) {
            // Add padding, border, margin
            val += paddingA + paddingB + marginA + marginB + borderA + borderB;
        }
    }

    return val;
}

[编辑] 您还需要从vanilla-masonry.js中获取hackPercentMargin和getStyle。


0
你可以查看jQuery源代码
// outerHeight and outerWidth
jQuery.fn[ "outer" + name ] = function( margin ) {
    var elem = this[0];
    return elem ?
        elem.style ?
        parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
        this[ type ]() :
        null;
};

我读了这段代码,但是我没看懂。使用 FireBug 调试 jQuery.fn.outerHeight 函数可以发现它使用了 jQuery.css 函数来获取结果。但是单步调试只会把我带进一堆递归调用和重命名函数中。 - maxquartermain

0
$('body').outerHeight(true) = document.body.height + document.body.marginTop + document.body.marginBottom + document.body.bordorTop + document.body.borderBottom

1
嗯 - document.body.height 等似乎不存在。document.body.style.height 等存在,但为空白。 - maxquartermain
el.style.height仅返回CSS中当前应用样式的值,该值可能为空、"auto"等。您想要的是实际的数字像素值,这就是getComputedStyle()所提供的。 - CletusW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接