我有下面的样本html,有一个DIV有100%的宽度。它包含了一些元素。在执行窗口调整大小时,内部元素可能会被重新定位,div的尺寸可能会改变。我在问是否有可能挂钩div的维度变化事件?以及如何做到这一点?我目前绑定回调函数到目标DIV上的jQuery调整大小事件,但是,没有输出控制台日志,如下所示:

<html>
<head>
    <script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
    <script type="text/javascript" language="javascript">
            $('#test_div').bind('resize', function(){
                console.log('resized');
            });
    </script>
</head>
<body>
    <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
        <input type="button" value="button 1" />
        <input type="button" value="button 2" />
        <input type="button" value="button 3" />
    </div>
</body>
</html>

当前回答

您可以尝试以下代码片段中的代码,它使用纯javascript满足您的需求。(如果您想测试div,则运行代码片段并单击整页链接以触发div调整大小的警报。)

基于这是一个100毫秒的setInterval的事实,我敢说我的PC没有发现它太多的CPU饥饿。(0.1%的CPU被用作测试时Chrome中所有打开的选项卡的总和。)但这只是一个div,如果你想为大量的元素这样做,那么是的,它可能是非常CPU饥饿。 无论如何,您总是可以使用单击事件来停止div-resize嗅探。

var width = 0; var interval = setInterval(function(){ if(width <= 0){ width = document.getElementById("test_div").clientWidth; } if(document.getElementById("test_div").clientWidth!==width) { alert('resized div'); width = document.getElementById("test_div").clientWidth; } }, 100); <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;"> <input type="button" value="button 1" /> <input type="button" value="button 2" /> <input type="button" value="button 3" /> </div>

你也可以检查一下小提琴

更新

var width = 0; function myInterval() { var interval = setInterval(function(){ if(width <= 0){ width = document.getElementById("test_div").clientWidth; } if(document.getElementById("test_div").clientWidth!==width) { alert('resized'); width = document.getElementById("test_div").clientWidth; } }, 100); return interval; } var interval = myInterval(); document.getElementById("clickMe").addEventListener( "click" , function() { if(typeof interval!=="undefined") { clearInterval(interval); alert("stopped div-resize sniffing"); } }); document.getElementById("clickMeToo").addEventListener( "click" , function() { myInterval(); alert("started div-resize sniffing"); }); <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;"> <input type="button" value="button 1" id="clickMe" /> <input type="button" value="button 2" id="clickMeToo" /> <input type="button" value="button 3" /> </div>

更新的小提琴

其他回答

从长远来看,您将能够使用ResizeObserver。

new ResizeObserver(callback).observe(element);

不幸的是,目前许多浏览器默认不支持它。

同时,您可以像下面这样使用函数。因为,大部分元素大小的变化将来自窗口大小的调整或DOM中的某些更改。你可以通过窗口的resize事件来监听窗口的大小调整,也可以使用MutationObserver监听DOM的变化。

下面是一个函数的例子,当提供的元素的大小因为这两个事件中的任何一个而改变时,它会回调你:

var onResize = function(element, callback) {
  if (!onResize.watchedElementData) {
    // First time we are called, create a list of watched elements
    // and hook up the event listeners.
    onResize.watchedElementData = [];

    var checkForChanges = function() {
      onResize.watchedElementData.forEach(function(data) {
        if (data.element.offsetWidth !== data.offsetWidth ||
            data.element.offsetHeight !== data.offsetHeight) {
          data.offsetWidth = data.element.offsetWidth;
          data.offsetHeight = data.element.offsetHeight;
          data.callback();
        }
      });
    };

    // Listen to the window's size changes
    window.addEventListener('resize', checkForChanges);

    // Listen to changes on the elements in the page that affect layout 
    var observer = new MutationObserver(checkForChanges);
    observer.observe(document.body, { 
      attributes: true,
      childList: true,
      characterData: true,
      subtree: true 
    });
  }

  // Save the element we are watching
  onResize.watchedElementData.push({
    element: element,
    offsetWidth: element.offsetWidth,
    offsetHeight: element.offsetHeight,
    callback: callback
  });
};

这几乎是顶部答案的精确副本,但不是链接,它只是重要的代码的一部分,翻译成IMO更易读,更容易理解。其他一些小的改变包括使用cloneNode(),和不把html放入js字符串。很小的东西,但是你可以复制粘贴它就可以了。

它的工作方式是让两个看不见的div填充你正在观看的元素,然后在每个div中设置一个触发器,并设置一个滚动位置,如果大小发生变化,将导致触发滚动变化。

所有真正的荣誉都属于Marc J,但如果你只是在寻找相关的代码,这里是:

    window.El = {}

    El.resizeSensorNode = undefined;
    El.initResizeNode = function() {
        var fillParent = "display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;";
        var triggerStyle = "position: absolute; left: 0; top: 0; transition: 0s;";

        var resizeSensor = El.resizeSensorNode = document.createElement("resizeSensor");
        resizeSensor.style = fillParent;

        var expandSensor = document.createElement("div");
        expandSensor.style = fillParent;
        resizeSensor.appendChild(expandSensor);

        var trigger = document.createElement("div");
        trigger.style = triggerStyle;
        expandSensor.appendChild(trigger);

        var shrinkSensor = expandSensor.cloneNode(true);
        shrinkSensor.firstChild.style = triggerStyle + " width: 200%; height: 200%";
        resizeSensor.appendChild(shrinkSensor);
    }


    El.onSizeChange = function(domNode, fn) {
        if (!domNode) return;
        if (domNode.resizeListeners) {
            domNode.resizeListeners.push(fn);
            return;
        }

        domNode.resizeListeners = [];
        domNode.resizeListeners.push(fn);

        if(El.resizeSensorNode == undefined)
            El.initResizeNode();

        domNode.resizeSensor = El.resizeSensorNode.cloneNode(true);
        domNode.appendChild(domNode.resizeSensor);

        var expand = domNode.resizeSensor.firstChild;
        var expandTrigger = expand.firstChild;
        var shrink = domNode.resizeSensor.childNodes[1];

        var reset = function() {
            expandTrigger.style.width = '100000px';
            expandTrigger.style.height = '100000px';

            expand.scrollLeft = 100000;
            expand.scrollTop = 100000;

            shrink.scrollLeft = 100000;
            shrink.scrollTop = 100000;
        };

        reset();

        var hasChanged, frameRequest, newWidth, newHeight;
        var lastWidth = domNode.offsetWidth;
        var lastHeight = domNode.offsetHeight;


        var onResized = function() {
            frameRequest = undefined;

            if (!hasChanged) return;

            lastWidth = newWidth;
            lastHeight = newHeight;

            var listeners = domNode.resizeListeners;
            for(var i = 0; listeners && i < listeners.length; i++) 
                listeners[i]();
        };

        var onScroll = function() {
            newWidth = domNode.offsetWidth;
            newHeight = domNode.offsetHeight;
            hasChanged = newWidth != lastWidth || newHeight != lastHeight;

            if (hasChanged && !frameRequest) {
                frameRequest = requestAnimationFrame(onResized);
            }

            reset();
        };


        expand.addEventListener("scroll", onScroll);
        shrink.addEventListener("scroll", onScroll);
    }

这篇博文帮助我有效地检测DOM元素的大小变化。

http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/

如何使用这段代码…

AppConfig.addResizeListener(document.getElementById('id'), function () {
  //Your code to execute on resize.
});

示例使用的打包代码…

var AppConfig = AppConfig || {};
AppConfig.ResizeListener = (function () {
    var attachEvent = document.attachEvent;
    var isIE = navigator.userAgent.match(/Trident/);
    var requestFrame = (function () {
        var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
            function (fn) { return window.setTimeout(fn, 20); };
        return function (fn) { return raf(fn); };
    })();

    var cancelFrame = (function () {
        var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
               window.clearTimeout;
        return function (id) { return cancel(id); };
    })();

    function resizeListener(e) {
        var win = e.target || e.srcElement;
        if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__);
        win.__resizeRAF__ = requestFrame(function () {
            var trigger = win.__resizeTrigger__;
            trigger.__resizeListeners__.forEach(function (fn) {
                fn.call(trigger, e);
            });
        });
    }

    function objectLoad(e) {
        this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
        this.contentDocument.defaultView.addEventListener('resize', resizeListener);
    }

    AppConfig.addResizeListener = function (element, fn) {
        if (!element.__resizeListeners__) {
            element.__resizeListeners__ = [];
            if (attachEvent) {
                element.__resizeTrigger__ = element;
                element.attachEvent('onresize', resizeListener);
            } else {
                if (getComputedStyle(element).position === 'static') element.style.position = 'relative';
                var obj = element.__resizeTrigger__ = document.createElement('object');
                obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
                obj.__resizeElement__ = element;
                obj.onload = objectLoad;
                obj.type = 'text/html';
                if (isIE) element.appendChild(obj);
                obj.data = 'about:blank';
                if (!isIE) element.appendChild(obj);
            }
        }
        element.__resizeListeners__.push(fn);
    };

    AppConfig.removeResizeListener = function (element, fn) {
        element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
        if (!element.__resizeListeners__.length) {
            if (attachEvent) element.detachEvent('onresize', resizeListener);
            else {
                element.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
                element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
            }
        }
    }
})();

注意:AppConfig是我用于组织可重用函数的名称空间/对象。请随意搜索并替换任何您想要的名称。

您必须将resize事件绑定到窗口对象上,而不是绑定到通用html元素上。

然后你可以使用这个:

$(window).resize(function() {
    ...
});

在回调函数中,你可以检查div调用的新宽度

$('.a-selector').width();

因此,您的问题的答案是否定的,您不能将resize事件绑定到div。

当MarcJ的解决方案不起作用时,我发现这个库可以工作:

https://github.com/sdecima/javascript-detect-element-resize

它是非常轻量级的,甚至可以通过CSS或简单的HTML加载/渲染来检测自然的大小调整。

代码示例(摘自链接):

<script type="text/javascript" src="detect-element-resize.js"></script>
<script type="text/javascript">
  var resizeElement = document.getElementById('resizeElement'),
      resizeCallback = function() {
          /* do something */
      };
  addResizeListener(resizeElement, resizeCallback);
  removeResizeListener(resizeElement, resizeCallback);
</script>