如何监听浏览器窗口缩放事件?
虽然有一种使用jQuery的方法监听resize事件,但我不想因为这一个需求而引入jQuery到我的项目中。
如何监听浏览器窗口缩放事件?
虽然有一种使用jQuery的方法监听resize事件,但我不想因为这一个需求而引入jQuery到我的项目中。
最佳实践是添加到resize事件,而不是替换它:
window.addEventListener('resize', function(event) {
...
}, true);
另一个选择是为DOM事件创建一个单一的处理程序(但只能有一个),例如:
window.onresize = function(event) {
...
};
jQuery 可能会做一些工作来确保在所有浏览器中一致地触发resize事件,但我不确定是否有任何浏览器存在差异,建议您在Firefox、Safari和IE中进行测试。
window.addEventListener('resize', function(){}, true);
- WebWandererwindow.onresize = () => { /* code */ };
或者更好的写法是:window.addEventListener('resize', () => { /* code */ });
。 - Derk Jan Speelman首先,我知道在上面的评论中提到了addEventListener
方法,但我没有看到任何代码。由于这是首选方法,所以在此提供:
window.addEventListener('resize', function(event){
// do stuff here
});
removeEventListener
来删除它。 - Stijn de Witt不要覆盖window.onresize函数。
相反,创建一个函数来向对象或元素添加事件监听器。如果监听器不起作用,则将覆盖对象的函数作为最后的手段。这是jQuery等库中使用的首选方法。
object
:元素或窗口对象
type
:resize,scroll(事件类型)
callback
:函数引用
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
} else if (object.attachEvent) {
object.attachEvent("on" + type, callback);
} else {
object["on"+type] = callback;
}
};
然后像这样使用:
addEvent(window, "resize", function_reference);
或使用匿名函数:
addEvent(window, "resize", function(event) {
console.log('resized');
});
attachEvent
。未来的首选方式是addEventListener
。 - Lukeelem == undefined
。虽然不太可能,但有可能“undefined”在本地被定义为其他值。参考链接:https://dev59.com/u13Ua4cB1Zd3GeqP_lzg - Luke2018年及以后的解决方案:
您应该使用 ResizeObserver 。 它是一个浏览器原生解决方案,比使用resize
事件性能更好。 此外,它不仅支持在document
上的事件,还支持在任意元素
上。
var ro = new ResizeObserver( entries => {
for (let entry of entries) {
const cr = entry.contentRect;
console.log('Element:', entry.target);
console.log(`Element size: ${cr.width}px x ${cr.height}px`);
console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
}
});
// Observe one or multiple elements
ro.observe(someElement);
目前,Firefox、Chrome、Safari 和 Edge 支持 Resize Observer。对于其他(以及较老的)浏览器,您需要使用polyfill来实现相同的功能。
addEventListener
时,您只需关注您感兴趣的元素;而使用ResizeObserver
时,您需要关注所有元素,因此我想知道它如何更高效。此外,如果您只关注一个元素,使用addEventListener
似乎更易读,而不是循环并找到正确的元素(是否应该有一个id)。我是否遗漏了什么? - undefined由于 resize 事件在调整大小时会不断触发,因此永远不应直接使用该事件。
请使用防抖函数来减少过多的调用。
window.addEventListener('resize',debounce(handler, delay, immediate),false);
这里是一个常见的 debounce 函数,在 lodash 中可能有更高级的版本。
const debounce = (func, wait, immediate) => {
var timeout;
return () => {
const context = this, args = arguments;
const later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
这可以像这样使用...
window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);
它永远不会以每200毫秒以上的速率触发。
对于移动设备方向更改,请使用:
window.addEventListener('orientationchange', () => console.log('hello'), false);
这是我整理的一个小型库,能够很好地处理此类问题。
(...arguments) => {...}
(或者为避免混淆可以使用...args
)作为参数,因为arguments
变量不再在其作用域中可用。 - coderatchet我相信@Alex V已经提供了正确的答案,但这个答案需要一些现代化,因为它已经超过五年了。
主要有两个问题:
不要使用object
作为参数名,它是一个保留字。因此,在strict mode
中,@Alex V提供的函数将无法工作。
@Alex V提供的addEvent
函数如果使用addEventListener
方法,则不会返回event object
。应该添加另一个参数到addEvent
函数中以支持这个功能。
注意:新参数被设置为可选,以便迁移到这个新版本函数不会破坏对此函数的任何先前调用。所有旧用途都将得到支持。
以下是更新后的addEvent
函数:
/*
function: addEvent
@param: obj (Object)(Required)
- The object which you wish
to attach your event to.
@param: type (String)(Required)
- The type of event you
wish to establish.
@param: callback (Function)(Required)
- The method you wish
to be called by your
event listener.
@param: eventReturn (Boolean)(Optional)
- Whether you want the
event object returned
to your callback method.
*/
var addEvent = function(obj, type, callback, eventReturn)
{
if(obj == null || typeof obj === 'undefined')
return;
if(obj.addEventListener)
obj.addEventListener(type, callback, eventReturn ? true : false);
else if(obj.attachEvent)
obj.attachEvent("on" + type, callback);
else
obj["on" + type] = callback;
};
使用新的addEvent
函数的示例调用:
var watch = function(evt)
{
/*
Older browser versions may return evt.srcElement
Newer browser versions should return evt.currentTarget
*/
var dimensions = {
height: (evt.srcElement || evt.currentTarget).innerHeight,
width: (evt.srcElement || evt.currentTarget).innerWidth
};
};
addEvent(window, 'resize', watch, true);
window.onresize = function() {
// your code
};
Sys.Application.add_load(function(sender, args) {
$addHandler(window, 'resize', window_resize);
});
var resizeTimeoutId;
function window_resize(e) {
window.clearTimeout(resizeTimeoutId);
resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}
如果您只想调整窗口大小,则上面提到的解决方案将起作用。但是,如果您希望将调整大小传播到子元素,则需要自己传播事件。以下是一些示例代码:
window.addEventListener("resize", function () {
var recResizeElement = function (root) {
Array.prototype.forEach.call(root.childNodes, function (el) {
var resizeEvent = document.createEvent("HTMLEvents");
resizeEvent.initEvent("resize", false, true);
var propagate = el.dispatchEvent(resizeEvent);
if (propagate)
recResizeElement(el);
});
};
recResizeElement(document.body);
});
event.preventDefault();
在传递给resize事件的第一个参数中,可以使用事件对象。例如:
var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
...
event.preventDefault();
});
<body onresize="yourHandler(event)">
function yourHandler(e) {
console.log('Resized:', e.target.innerWidth)
}
<body onresize="yourHandler(event)">
Content... (resize browser to see)
</body>