我有下面的样本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>
看看这个http://benalman.com/code/projects/jquery-resize/examples/resize/
它有很多例子。尝试调整窗口大小,看看容器元素中的元素是如何调整的。
用js的例子来解释如何让它工作。
看看这小提琴http://jsfiddle.net/sgsqJ/4/
在这个resize()事件中,它被绑定到具有类“test”的元素以及窗口对象
在窗口对象$('.test')的resize回调中调用.resize()。
e.g.
$('#test_div').bind('resize', function(){
console.log('resized');
});
$(window).resize(function(){
$('#test_div').resize();
});
您可以尝试以下代码片段中的代码,它使用纯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>
更新的小提琴
最好的解决方案是使用所谓的元素查询。然而,它们不是标准的,没有规范存在——如果你想这样做,唯一的选择是使用一个可用的腻子库/库。
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。
下面是@nkron的简化版本的解决方案,适用于单个元素(而不是@nkron的答案中的元素数组,我不需要复杂性)。
function onResizeElem(element, callback) {
// Save the element we are watching
onResizeElem.watchedElementData = {
element: element,
offsetWidth: element.offsetWidth,
offsetHeight: element.offsetHeight,
callback: callback
};
onResizeElem.checkForChanges = function() {
const data = onResizeElem.watchedElementData;
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 resize event
window.addEventListener('resize', onResizeElem.checkForChanges);
// Listen to the element being checked for width and height changes
onResizeElem.observer = new MutationObserver(onResizeElem.checkForChanges);
onResizeElem.observer.observe(document.body, {
attributes: true,
childList: true,
characterData: true,
subtree: true
});
}
事件监听器和观察者可以通过以下方式删除:
window.removeEventListener('resize', onResizeElem.checkForChanges);
onResizeElem.observer.disconnect();