如何挂钩浏览器窗口调整大小事件?
有一种侦听调整大小事件的jQuery方式,但是我不希望仅出于这一需求就将其引入我的项目中。
如何挂钩浏览器窗口调整大小事件?
有一种侦听调整大小事件的jQuery方式,但是我不希望仅出于这一需求就将其引入我的项目中。
Answers:
jQuery只是包装了标准的resize
DOM事件,例如。
window.onresize = function(event) {
...
};
jQuery 可以做一些工作来确保在所有浏览器中一致地触发resize事件,但是我不确定是否有任何浏览器有所不同,但是我建议您在Firefox,Safari和IE中进行测试。
window.addEventListener('resize', function(){}, true);
window.onresize = () => { /* code */ };
或更好:window.addEventListener('resize', () => { /* code */ });
首先,我知道 addEventListener
上面的注释中已经提到了方法,但是我没有看到任何代码。由于这是首选方法,因此它是:
window.addEventListener('resize', function(event){
// do stuff here
});
removeEventListener
。
切勿覆盖window.onresize函数。
而是,创建一个将事件侦听器添加到对象或元素的函数。这会检查并防止侦听器不起作用,然后作为最后手段重写该对象的功能。这是在jQuery之类的库中使用的首选方法。
object
:元素或窗口对象
type
:调整大小,滚动(事件类型)
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
。
elem == undefined
。有可能(尽管不太可能)在本地将“未定义”定义为其他内容。stackoverflow.com/questions/8175673/…–
调整大小事件永远不要直接使用,因为它在调整大小时会连续触发。
使用去抖动功能来减轻过多的呼叫。
window.addEventListener('resize',debounce(handler, delay, immediate),false);
这是一种常见的在网上浮动的反跳,尽管确实会在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);
每200ms发射一次就不会超过一次。
对于移动方向更改,请使用:
window.addEventListener('orientationchange', () => console.log('hello'), false);
我整理了一个小图书馆来妥善处理这个问题。
(...arguments) => {...}
(或...args
为了减少混淆),因为该arguments
变量在其作用域中不再可用。
2018年以上的解决方案:
您应该使用ResizeObserver。它是浏览器本地解决方案,其性能要比使用resize
事件好得多。此外,它不仅支持on事件,document
而且还支持任意事件elements
。
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支持它。对于其他(或更旧的)浏览器,您必须使用polyfill。
我确实相信@Alex V已经提供了正确的答案,但是答案确实需要一些现代化,因为它已经超过5年了。
有两个主要问题:
切勿将其object
用作参数名称。这是一个保留字。话虽如此,@Alex V提供的功能将无法在中使用strict mode
。
如果使用该方法addEvent
,@ Alex V提供的函数不会返回。应该在函数中添加另一个参数以允许这样做。event object
addEventListener
addEvent
注意: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);
感谢您在http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html中引用我的博客文章。
尽管您可以连接到标准窗口调整大小事件,但您会发现在IE中,该事件每X触发一次,每Y轴移动触发一次,导致触发大量事件,这可能会产生性能如果渲染是一项繁重的任务,则会对您的网站产生影响。
我的方法涉及一个短暂的超时,该超时将在后续事件中取消,以便在用户完成调整窗口大小之前,该事件不会冒泡到您的代码中。
以下博客文章可能对您有用:在IE中修复窗口调整大小事件
它提供了以下代码:
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();
在作为调整大小事件的第一个Arg传入的事件对象上。例如:
var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
...
event.preventDefault();
});
var EM = new events_managment();
EM.addEvent(window, 'resize', function(win,doc, event_){
console.log('resized');
//EM.removeEvent(win,doc, event_);
});
function events_managment(){
this.events = {};
this.addEvent = function(node, event_, func){
if(node.addEventListener){
if(event_ in this.events){
node.addEventListener(event_, function(){
func(node, event_);
this.events[event_](win_doc, event_);
}, true);
}else{
node.addEventListener(event_, function(){
func(node, event_);
}, true);
}
this.events[event_] = func;
}else if(node.attachEvent){
var ie_event = 'on' + event_;
if(ie_event in this.events){
node.attachEvent(ie_event, function(){
func(node, ie_event);
this.events[ie_event]();
});
}else{
node.attachEvent(ie_event, function(){
func(node, ie_event);
});
}
this.events[ie_event] = func;
}
}
this.removeEvent = function(node, event_){
if(node.removeEventListener){
node.removeEventListener(event_, this.events[event_], true);
this.events[event_] = null;
delete this.events[event_];
}else if(node.detachEvent){
node.detachEvent(event_, this.events[event_]);
this.events[event_] = null;
delete this.events[event_];
}
}
}