我有下面的样本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>

当前回答

使用Clay.js (https://github.com/zzarcon/clay),检测元素大小的变化非常简单:

var el = new Clay('.element');

el.on('resize', function(size) {
    console.log(size.height, size.width);
});

其他回答

我认为这是不可能的,但后来我想了一下,你可以手动调整一个div通过style="resize: both;"为了做到这一点,你必须点击它,所以添加了一个onclick函数来检查元素的高度和宽度,它工作。只有5行纯javascript(当然可以更短) http://codepen.io/anon/pen/eNyyVN

<div id="box" style="
                height:200px; 
                width:640px;
                background-color:#FF0066;
                resize: both;
                overflow: auto;" 
                onclick="myFunction()">
    <p id="sizeTXT" style="
                font-size: 50px;">
       WxH
    </p>
    </div>

<p>This my example demonstrates how to run a resize check on click for resizable div.</p>

<p>Try to resize the box.</p>


<script>
function myFunction() {
var boxheight = document.getElementById('box').offsetHeight;
var boxhwidth = document.getElementById('box').offsetWidth;
var txt = boxhwidth +"x"+boxheight;
document.getElementById("sizeTXT").innerHTML = txt;
}
</script>

ResizeSensor.js是一个巨大库的一部分,但我把它的功能简化为:

function ResizeSensor(element, callback)
{
    let zIndex = parseInt(getComputedStyle(element));
    if(isNaN(zIndex)) { zIndex = 0; };
    zIndex--;

    let expand = document.createElement('div');
    expand.style.position = "absolute";
    expand.style.left = "0px";
    expand.style.top = "0px";
    expand.style.right = "0px";
    expand.style.bottom = "0px";
    expand.style.overflow = "hidden";
    expand.style.zIndex = zIndex;
    expand.style.visibility = "hidden";

    let expandChild = document.createElement('div');
    expandChild.style.position = "absolute";
    expandChild.style.left = "0px";
    expandChild.style.top = "0px";
    expandChild.style.width = "10000000px";
    expandChild.style.height = "10000000px";
    expand.appendChild(expandChild);

    let shrink = document.createElement('div');
    shrink.style.position = "absolute";
    shrink.style.left = "0px";
    shrink.style.top = "0px";
    shrink.style.right = "0px";
    shrink.style.bottom = "0px";
    shrink.style.overflow = "hidden";
    shrink.style.zIndex = zIndex;
    shrink.style.visibility = "hidden";

    let shrinkChild = document.createElement('div');
    shrinkChild.style.position = "absolute";
    shrinkChild.style.left = "0px";
    shrinkChild.style.top = "0px";
    shrinkChild.style.width = "200%";
    shrinkChild.style.height = "200%";
    shrink.appendChild(shrinkChild);

    element.appendChild(expand);
    element.appendChild(shrink);

    function setScroll()
    {
        expand.scrollLeft = 10000000;
        expand.scrollTop = 10000000;

        shrink.scrollLeft = 10000000;
        shrink.scrollTop = 10000000;
    };
    setScroll();

    let size = element.getBoundingClientRect();

    let currentWidth = size.width;
    let currentHeight = size.height;

    let onScroll = function()
    {
        let size = element.getBoundingClientRect();

        let newWidth = size.width;
        let newHeight = size.height;

        if(newWidth != currentWidth || newHeight != currentHeight)
        {
            currentWidth = newWidth;
            currentHeight = newHeight;

            callback();
        }

        setScroll();
    };

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

如何使用:

let container = document.querySelector(".container");
new ResizeSensor(container, function()
{
    console.log("dimension changed:", container.clientWidth, container.clientHeight);
});

我不建议使用setTimeout(),因为它会降低性能! 相反,你可以使用DOM ResizeObserver方法来监听Div大小的变化。

const myObserver = new ResizeObserver(entries => {
 // this will get called whenever div dimension changes
  entries.forEach(entry => {
    console.log('width', entry.contentRect.width);
    console.log('height', entry.contentRect.height);
  });
});

const someEl = document.querySelector('.some-element');

// start listening to changes
myObserver.observe(someEl);

// later, stop listening to changes
myObserver.disconnect();

使用MutationObserver的旧答案:

用于监听HTML元素属性、子树和类的更改:

JS:

    var observer = new MutationObserver(function(mutations) {
        console.log('size changed!');
      });
      var target = document.querySelector('.mydiv');
      observer.observe(target, {
        attributes: true,
        childList: true,
        subtree: true
      });

HTML:

    <div class='mydiv'>
    </div>

这是小提琴。试着改变div大小。


您可以将您的方法进一步封装在debounce方法中以提高效率。debounce将每x毫秒触发一次你的方法,而不是在DIV被调整大小的每一毫秒触发一次。

最好的解决方案是使用所谓的元素查询。然而,它们不是标准的,没有规范存在——如果你想这样做,唯一的选择是使用一个可用的腻子库/库。

The idea behind element queries is to allow a certain container on the page to respond to the space that's provided to it. This will allow to write a component once and then drop it anywhere on the page, while it will adjust its contents to its current size. No matter what the Window size is. This is the first difference that we see between element queries and media queries. Everyone hopes that at some point a specification will be created that will standardize element queries (or something that achieves the same goal) and make them native, clean, simple and robust. Most people agree that Media queries are quite limited and don't help for modular design and true responsiveness.

有一些腻子/库可以用不同的方式解决这个问题(可以称为变通方案而不是解决方案):

CSS元素查询- https://github.com/marcj/css-element-queries BoomQueries - https://github.com/BoomTownROI/boomqueries eq.js - https://github.com/Snugug/eq.js ElementQuery - https://github.com/tysonmatanich/elementQuery 还有一些,我不打算在这里列出,但你可以自由搜索。我不能说目前可用的选项中哪一个是最好的。你得试几样再决定。

我看到过针对类似问题提出的其他解决方案。通常他们使用计时器或窗口/视口大小,这不是一个真正的解决方案。此外,我认为理想情况下,这个问题应该主要用CSS来解决,而不是javascript或html。

通过@gman扩展这个答案,这里有一个允许每个元素多次回调的函数,将宽度和高度分解为一个准事件对象。请参阅关于堆栈溢出的嵌入式演示(您可能需要彻底调整主浏览器的大小以触发它)

function elementResizeWatcher(element, callback) { var resolve=function(element) { return (typeof element==='string' ? document[ ['.','#'].indexOf(element.charAt(0)) < 0 ? "getElementById" : "querySelector" ] (element) : element); }, observer, watched = [], checkForElementChanges = function (data) { var w=data.el.offsetWidth,h=data.el.offsetHeight; if ( data.offsetWidth !== w || data.offsetHeight !== h ) { data.offsetWidth = w; data.offsetHeight = h; data.cb({ target : data.el, width : w, height : h }); } }, checkForChanges=function(){ watched.forEach(checkForElementChanges); }, started=false, self = { start: function () { if (!started) { // Listen to the window resize event window.addEventListener("resize", checkForChanges); // Listen to the element being checked for width and height changes observer = new MutationObserver(checkForChanges); observer.observe(document.body, { attributes: true, childList: true, characterData: true, subtree: true }); started=true; } }, stop : function ( ) { if (started) { window.removeEventListener('resize', checkForChanges); observer.disconnect(); started = false; } }, addListener : function (element,callback) { if (typeof callback!=='function') return; var el = resolve(element); if (typeof el==='object') { watched.push({ el : el, offsetWidth : el.offsetWidth, offsetHeight : el.offsetHeight, cb : callback }); } }, removeListener : function (element,callback) { var el = resolve(element); watched = watched.filter(function(data){ return !((data.el===el) && (data.cb===callback)); }); } }; self.addListener(element,callback); self.start(); return self; } var watcher = elementResizeWatcher("#resize_me_on_stack_overflow", function(e){ e.target.innerHTML="i am "+e.width+"px&nbsp;x&nbsp;"+e.height+"px"; }); watcher.addListener(".resize_metoo",function(e) { e.target.innerHTML="and i am "+e.width+"px&nbsp;x&nbsp;"+e.height+"px"; }); var mainsize_info = document.getElementById("mainsize"); watcher.addListener(document.body,function(e) { mainsize_info.innerHTML=e.width+"px&nbsp;x&nbsp;"+e.height+"px"; }); #resize_me_on_stack_overflow{ background-color:lime; } .resize_metoo { background-color:yellow; font-size:36pt; width:50%; } <p> resize the main browser window! <span id="mainsize"><span> </p> <p id="resize_me_on_stack_overflow"> hey, resize me. </p> <p class="resize_metoo"> resize me too. </p>