我有下面的样本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>
这是一个非常老的问题,但我想我会把我的解决方案贴出来。
我尝试使用resizsensor,因为每个人似乎都对它有很大的好感。在实现之后,我意识到在底层,元素查询要求所讨论的元素具有相对位置或绝对位置,这不适用于我的情况。
我最终用Rxjs间隔来处理这个问题,而不是像以前的实现那样直接使用setTimeout或requestAnimationFrame。
间隔的可观察对象的好处在于,你可以修改流,但任何其他可观察对象都可以被处理。对我来说,一个基本的实现就足够了,但是你可以疯狂地做各种各样的合并等等。
在下面的例子中,我正在跟踪内部(绿色)div的宽度变化。它的宽度设置为50%,但max-width为200px。拖动滑块会影响包装器(灰色)div的宽度。你可以看到,只有当内部div的宽度发生变化时,可观察对象才会触发,只有当外部div的宽度小于400px时才会发生这种情况。
const { interval } = rxjs;
const { distinctUntilChanged, map, filter } = rxjs.operators;
const wrapper = document.getElementById('my-wrapper');
const input = document.getElementById('width-input');
function subscribeToResize() {
const timer = interval(100);
const myDiv = document.getElementById('my-div');
const widthElement = document.getElementById('width');
const isMax = document.getElementById('is-max');
/*
NOTE: This is the important bit here
*/
timer
.pipe(
map(() => myDiv ? Math.round(myDiv.getBoundingClientRect().width) : 0),
distinctUntilChanged(),
// adding a takeUntil(), here as well would allow cleanup when the component is destroyed
)
.subscribe((width) => {
widthElement.innerHTML = width;
isMax.innerHTML = width === 200 ? 'Max width' : '50% width';
});
}
function defineRange() {
input.min = 200;
input.max = window.innerWidth;
input.step = 10;
input.value = input.max - 50;
}
function bindInputToWrapper() {
input.addEventListener('input', (event) => {
wrapper.style.width = `${event.target.value}px`;
});
}
defineRange();
subscribeToResize();
bindInputToWrapper();
.inner {
width: 50%;
max-width: 200px;
}
/* Aesthetic styles only */
.inner {
background: #16a085;
}
.wrapper {
background: #ecf0f1;
color: white;
margin-top: 24px;
}
.content {
padding: 12px;
}
body {
font-family: sans-serif;
font-weight: bold;
}
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>
<h1>Resize Browser width</h1>
<label for="width-input">Adjust the width of the wrapper element</label>
<div>
<input type="range" id="width-input">
</div>
<div id="my-wrapper" class="wrapper">
<div id="my-div" class="inner">
<div class="content">
Width: <span id="width"></span>px
<div id="is-max"></div>
</div>
</div>
</div>
您可以尝试以下代码片段中的代码,它使用纯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>
更新的小提琴