JavaScript窗口大小调整事件
我怎样才能钩入浏览器窗口resize事件?
有一种监听resize事件的jQuery方法,但是我不希望将这个方法带入我的项目中。
jQuery只是包装标准的resize
DOM事件,例如。
window.onresize = function(event) { ... };
jQuery 可能会做一些工作以确保resize事件在所有浏览器中一致地被触发,但是我不确定是否有任何浏览器有所不同,但是我build议您在Firefox,Safari和IE中进行testing。
切勿覆盖window.onresize函数。
相反,创build一个函数来将Event Listener添加到对象或元素。 这将检查并避免侦听器不工作,那么它将覆盖对象的函数作为最后的手段。 这是在jQuery等库中使用的首选方法。
object
:元素或窗口对象
type
:resize,scroll(事件types)
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);
或者使用匿名function:
addEvent(window, "resize", function(event) { console.log('resized'); });
首先,我知道上面的注释中已经提到了addEventListener
方法,但是我没有看到任何代码。 由于这是首选方法,因此它是:
window.addEventListener('resize', function(event){ // do stuff here });
这是一个工作示例 。
感谢您在http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html上引用我的博客文章。;
虽然你可以连接到标准的窗口大小事件,你会发现,在IE浏览器中,每发生一次X事件,每发生一次Y轴事件都会触发事件,导致大量的事件被触发,如果渲染是一项密集型任务,则会影响您的网站。
我的方法涉及一个短暂的超时,在随后的事件中取消,这样事件不会冒泡到您的代码,直到用户完成窗口的大小调整。
我确实相信@Alex V已经提供了正确的答案,但是现在的答案确实需要一些现代化。
有两个主要问题:
-
永远不要使用
object
作为参数名称。 这是一个储备的词。 有了这个说法,@Alex V提供的function将不能在strict mode
工作。 -
如果使用
addEventListener
方法,@Alex V提供的addEvent
函数不返回event object
。 另外一个参数应该添加到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);
window.onresize = function() { // your code };
resize事件不应该被直接使用,因为它会在我们resize时被连续触发。
使用去抖function来减轻多余的呼叫。
window.addEventListener('resize',debounce(handler, delay, immediate),false);
这里有一个常见的反弹动作,尽pipe在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);
这里有一个小型的图书馆,我把它放在一起照顾整齐。
以下博客文章可能对您有用: 在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); }
<script language="javascript"> window.onresize = function() { document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%'; } </script>
上面已经提到的解决scheme将工作,如果你只想调整窗口和窗口的大小。 但是,如果要将resize传播到子元素,则需要自行传播事件。 以下是一些示例代码:
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事件的第一个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_]; } } }