Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 检测文档高度变化_Javascript_Domdocument - Fatal编程技术网

Javascript 检测文档高度变化

Javascript 检测文档高度变化,javascript,domdocument,Javascript,Domdocument,我正在尝试检测我的文档高度何时发生变化。一旦完成,我需要运行一些函数来帮助组织我的页面布局 我不是在找window.onresize。我需要整个文档,它比窗口大 如何观察此更改?正如vsync所述,没有事件,但您可以使用计时器或将处理程序附加到其他地方: // get the height var refreshDocHeight = function(){ var h = $(document).height(); $('#result').html("Document hei

我正在尝试检测我的
文档
高度何时发生变化。一旦完成,我需要运行一些函数来帮助组织我的页面布局

我不是在找
window.onresize
。我需要整个文档,它比窗口大


如何观察此更改?

正如vsync所述,没有事件,但您可以使用计时器或将处理程序附加到其他地方:

// get the height
var refreshDocHeight = function(){
    var h = $(document).height();
    $('#result').html("Document height: " + h);
};

// update the height every 200ms
window.setInterval(refreshDocHeight, 200);

// or attach the handler to all events which are able to change 
// the document height, for example
$('div').keyup(refreshDocHeight);
查找。

命令watch()检查属性中的任何更改

见此。

更新(2020年10月): 是一个很棒的API()

//创建一个观察者实例
const resizeObserver=新的resizeObserver(条目=>
console.log('Body height changed:',条目[0]。target.clientHeight)
)
//开始观察DOM节点
resizeObserver.observe(document.body)
//单击任意位置以调整高度
window.addEventListener('click',()=>
document.body.style.height=Math.floor((Math.random()*5000)+1)+“px”
)

单击任意位置更改高度
只要我的两分钱。如果您正在使用angular,那么这将完成以下工作:

$scope.$watch(function(){ 
 return document.height();
},function onHeightChange(newValue, oldValue){
 ...
});

您可以在要监视高度变化的元素内部使用宽度为零的
绝对
定位
iframe
,并在其
内容窗口上收听
调整大小
事件。例如:

HTML

JavaScript(使用jQuery,但可以适应纯JS)

如果出于任何原因,在
body
上设置了
height:100%
,则需要找到(或添加)另一个容器元素来实现此设置。如果要动态添加
iframe
,可能需要使用
.load
事件来附加
contentWindow.resize
侦听器。如果您想让它在IE7和浏览器中都能工作,您需要将
*zoom:1
hack添加到container元素中,还需要监听
元素本身上的“专有”
resize
事件(这将复制IE8-10中的
contentWindow.resize


…vsync的答案完全正确。以防您不喜欢使用
setTimeout
,您可以使用
requestAnimationFrame
(),当然您仍然感兴趣

在下面的示例中,主体获取一个额外的事件
sizechange
。每次身体的高度或宽度改变时,它就会被触发

(function checkForBodySizeChange() {
    var last_body_size = {
        width: document.body.clientWidth,
        height: document.body.clientHeight
    };

    function checkBodySizeChange()
    {
        var width_changed = last_body_size.width !== document.body.clientWidth,
            height_changed = last_body_size.height !== document.body.clientHeight;


        if(width_changed || height_changed) {
            trigger(document.body, 'sizechange');
            last_body_size = {
                width: document.body.clientWidth,
                height: document.body.clientHeight
            };
        }

        window.requestAnimationFrame(checkBodySizeChange);
    }

    function trigger(element, event_name, event_detail)
    {
        var evt;

        if(document.dispatchEvent) {
            if(typeof CustomEvent === 'undefined') {
                var CustomEvent;

                CustomEvent = function(event, params) {
                    var evt;
                    params = params || {
                        bubbles: false,
                        cancelable: false,
                        detail: undefined
                    };
                    evt = document.createEvent("CustomEvent");
                    evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
                    return evt;
                };

                CustomEvent.prototype = window.Event.prototype;

                window.CustomEvent = CustomEvent;
            }

            evt = new CustomEvent(event_name, {"detail": event_detail});

            element.dispatchEvent(evt);
        }
        else {
            evt = document.createEventObject();
            evt.eventType = event_name;
            evt.eventName = event_name;
            element.fireEvent('on' + event_name, evt);
        }
    }

    window.requestAnimationFrame(checkBodySizeChange);
})();


如果您在项目中有自己的
triggerEvent
函数,那么代码可以大大减少。因此,只需删除完整的函数
trigger
并替换行
trigger(document.body,'sizechange')以jQuery
$(document.body.trigger('sizechange')为例

我正在使用@vsync的解决方案,如下所示。我用它在twitter这样的页面上自动滚动

const scrollInterval = (timeInterval, retry, cb) => {
    let tmpHeight = 0;
    const myInterval = setInterval(() => {
        console.log('interval');
        if (retry++ > 3) {
            clearInterval(this);
        }
        const change = document.body.clientHeight - tmpHeight;
        tmpHeight = document.body.clientHeight;
        if (change > 0) {
            cb(change, (retry * timeInterval));
            scrollBy(0, 10000);
        }
        retry = 0;
    }, timeInterval);
    return myInterval;
};

const onBodyChange = (change, timeout) => {
    console.log(`document.body.clientHeight, changed: ${change}, after: ${timeout}`);
}

const createdInterval = scrollInterval(500, 3, onBodyChange);

// stop the scroller on some event
setTimeout(() => {
    clearInterval(createdInterval);
}, 10000);

您还可以添加最小更改,以及许多其他内容。。。但这对我来说是有效的更新:2020

现在有一种方法可以使用新的。这允许您在元素的大小发生变化时,收听整个元素列表。基本用法相当简单:

const observer = new ResizeObserver(entries => {
  for (const entry of entries) {
    // each entry is an instance of ResizeObserverEntry
    console.log(entry.contentRect.height)
  }
})
observer.observe(document.querySelector('body'))
一个缺点是,目前只支持Chrome/Firefox,但是你可以在那里找到一些可靠的填充。下面是我写的一个代码笔示例:


嗯,实际上没有这样的事件,我想你必须使用计时器函数。我希望避免这种递归。另外,它会让人紧张。试试这个:我做了,但它对我不起作用。它似乎没有捕捉到我的
$.animate()
s,但它确实会在删除/添加元素时进行拾取。相关-WATCH命令不是标准命令,只有GECKO支持。。但是您可以使用polyfill:看到了吗?“一般来说,如果可能的话,你应该避免使用watch()和unwatch()。这两种方法只在Gecko中实现,它们主要用于调试。此外,使用watchpoint对性能有严重的负面影响”这是一个很好的回答+1.真遗憾,这种变化没有一个标准的活动!我知道我在这里挖掘一个老帖子,但是checkDocumentheight函数会一直运行,对吗?这似乎会使浏览器一次又一次地检查文档高度的速度变慢。@Cloudkiller-是的,它经常运行,是的,它会影响性能,但我知道没有更好的方法。@ShashwatTripathi-我看不出它不起作用的原因。请调试它,并解释哪段代码不能具体工作。iPad也是一种设备,而不是浏览器。哪个浏览器出了问题?@vsync,实际上,在一个页面中,我已经设置了iframe,并且我已经成功地设置了iframe height=iframe的内部内容在onload时的高度,并调整了外部页面的大小事件,这样就避免了滚动,现在在控件悬停(位于底部)的iframe内容中显示了一个弹出窗口。所以我的iframe现在有滚动,我不想在悬停该项时滚动它,你是说$(document.height()?这是行不通的,它只会检查angular scope$digest上的高度,这并没有涵盖高度可以改变的许多其他方式,因为css动画、图像加载和任何不会触发角度摘要的js代码(例如非角度LIB)答案清楚地指出“如果有机会,您正在使用angular”。话虽如此,对于基于角度的应用程序,上述代码做得很好。我认为这是一个相当聪明的解决方案,但是出于您描述的原因,最好使用
100vh
而不是
100%
。但是,您将失去与某些不支持视口高度的旧浏览器的兼容性。@Tim-
100vh
将是视口(又名窗口)的高度,而我们希望在更改时检测文档的高度(即内容,它不是同一事物),这是
100%
提供的。(当视口高度随
窗口.resize
事件变化时,很容易检测到。)你说得对,不知道为什么
(function checkForBodySizeChange() {
    var last_body_size = {
        width: document.body.clientWidth,
        height: document.body.clientHeight
    };

    function checkBodySizeChange()
    {
        var width_changed = last_body_size.width !== document.body.clientWidth,
            height_changed = last_body_size.height !== document.body.clientHeight;


        if(width_changed || height_changed) {
            trigger(document.body, 'sizechange');
            last_body_size = {
                width: document.body.clientWidth,
                height: document.body.clientHeight
            };
        }

        window.requestAnimationFrame(checkBodySizeChange);
    }

    function trigger(element, event_name, event_detail)
    {
        var evt;

        if(document.dispatchEvent) {
            if(typeof CustomEvent === 'undefined') {
                var CustomEvent;

                CustomEvent = function(event, params) {
                    var evt;
                    params = params || {
                        bubbles: false,
                        cancelable: false,
                        detail: undefined
                    };
                    evt = document.createEvent("CustomEvent");
                    evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
                    return evt;
                };

                CustomEvent.prototype = window.Event.prototype;

                window.CustomEvent = CustomEvent;
            }

            evt = new CustomEvent(event_name, {"detail": event_detail});

            element.dispatchEvent(evt);
        }
        else {
            evt = document.createEventObject();
            evt.eventType = event_name;
            evt.eventName = event_name;
            element.fireEvent('on' + event_name, evt);
        }
    }

    window.requestAnimationFrame(checkBodySizeChange);
})();
const scrollInterval = (timeInterval, retry, cb) => {
    let tmpHeight = 0;
    const myInterval = setInterval(() => {
        console.log('interval');
        if (retry++ > 3) {
            clearInterval(this);
        }
        const change = document.body.clientHeight - tmpHeight;
        tmpHeight = document.body.clientHeight;
        if (change > 0) {
            cb(change, (retry * timeInterval));
            scrollBy(0, 10000);
        }
        retry = 0;
    }, timeInterval);
    return myInterval;
};

const onBodyChange = (change, timeout) => {
    console.log(`document.body.clientHeight, changed: ${change}, after: ${timeout}`);
}

const createdInterval = scrollInterval(500, 3, onBodyChange);

// stop the scroller on some event
setTimeout(() => {
    clearInterval(createdInterval);
}, 10000);
const observer = new ResizeObserver(entries => {
  for (const entry of entries) {
    // each entry is an instance of ResizeObserverEntry
    console.log(entry.contentRect.height)
  }
})
observer.observe(document.querySelector('body'))