Ereignis zur Größenänderung des JavaScript-Fensters


617

Wie kann ich mich in ein Browserfenster einbinden, um die Größe zu ändern?

Es gibt eine jQuery-Methode, um auf Größenänderungsereignisse zu warten, aber ich würde es vorziehen, sie nicht nur für diese eine Anforderung in mein Projekt aufzunehmen.


8
Vielen Dank an alle. IE ist mir egal, ich habe mehr darüber nachgedacht, die Größe für die Oper auf einem Mobiltelefon zu ändern.
Dead Account

Antworten:


640

jQuery verpackt nur das Standard- resizeDOM-Ereignis, z.

window.onresize = function(event) {
    ...
};

jQuery kann einige Arbeiten ausführen, um sicherzustellen, dass das Größenänderungsereignis in allen Browsern konsistent ausgelöst wird. Ich bin mir jedoch nicht sicher, ob sich einer der Browser unterscheidet. Ich möchte Sie jedoch dazu ermutigen, Tests in Firefox, Safari und IE durchzuführen.


226
Ein mögliches Problem bei dieser Methode ist, dass Sie das Ereignis überschreiben und daher nicht mehrere Aktionen an ein Ereignis anhängen können. Die Kombination addEventListener / attachEvent ist der beste Weg, um Ihr Javascript mit jedem anderen Skript, das möglicherweise auf der Seite ausgeführt wird, spielfreundlich zu gestalten.
MyItchyChin

4
var onresize = window.onresize; window.onresize = function (event) {if (typeof onresize === 'function') onresize (); / ** ... * /}
SubOne

230
window.addEventListener('resize', function(){}, true);
WebWanderer

16
@SubOne ein perfektes Beispiel dafür, wie man es niemals tun sollte.
Eugene Pankov

28
ECMAScript 6 : window.onresize = () => { /* code */ };oder besser:window.addEventListener('resize', () => { /* code */ });
Derk Jan Speelman

561

Zunächst einmal weiß ich, dass die addEventListenerMethode in den obigen Kommentaren erwähnt wurde, aber ich habe keinen Code gesehen. Da es der bevorzugte Ansatz ist, ist es hier:

window.addEventListener('resize', function(event){
  // do stuff here
});

Hier ist ein Arbeitsbeispiel .


63
Dies ist die einfachste Antwort.
Jacoviza

7
Klingt nach der besten Antwort, weil Sie das window.onresize-Ereignis nicht überschreiben :-)
James Harrington

27
Viele Leute fügen anonyme Ereignis-Listener hinzu, wie Sie es in diesem Beispiel tun, aber es ist keine wirklich gute Praxis, da dieser Ansatz es unmöglich macht , diese Listener später zu entfernen. Früher war dies kein Problem, da Webseiten ohnehin nur von kurzer Dauer waren, aber in der heutigen Zeit von AJAX, RIAs und SPAs wird es eine. Wir brauchen eine Möglichkeit, den Lebenszyklus von Ereignis-Listenern zu verwalten. Daher ist es besser, die Listener-Funktion in eine separate Funktion zu zerlegen, damit sie später mit entfernt werden kann removeEventListener.
Stijn de Witt

6
warum kann nicht jeder so antworten ohne all den Flaum
quemeful

2
Ich denke, dass die Antworten von Stijn de Witt und quemeful hier wahr sind. Manchmal ist es Ihnen wichtig, Ereignis-Listener zu entfernen, aber falls Sie dies nicht tun, ist das Hinzufügen des gesamten zusätzlichen Codes wie im obigen Beispiel nicht erforderlich und kann sowohl zum Aufblähen als auch zur Lesbarkeit führen. Meiner Meinung nach ist dieser Ansatz die beste Lösung, wenn Sie sich keinen Grund vorstellen, den Listener zu entfernen. Sie können es später bei Bedarf jederzeit neu schreiben. Nach meiner Erfahrung treten diese Bedürfnisse nur in bestimmten Situationen auf.
Cazort

524

Überschreiben Sie niemals die Funktion window.onresize.

Erstellen Sie stattdessen eine Funktion, um dem Objekt oder Element einen Ereignis-Listener hinzuzufügen. Dies überprüft und falls die Listener nicht funktionieren, überschreibt es die Funktion des Objekts als letzten Ausweg. Dies ist die bevorzugte Methode, die in Bibliotheken wie jQuery verwendet wird.

object: das Element oder Fensterobjekt
type: Größe ändern, scrollen (Ereignistyp)
callback: die Funktionsreferenz

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;
    }
};

Dann ist die Verwendung wie folgt:

addEvent(window, "resize", function_reference);

oder mit einer anonymen Funktion:

addEvent(window, "resize", function(event) {
  console.log('resized');
});

100
Dies sollte die akzeptierte Antwort gewesen sein. Das Überschreiben von Onresize ist nur eine schlechte Praxis.
Tiberiu-Ionuț Stan

8
hah, was ist mit all den zusätzlichen Nullprüfungen? versuchen in IE 4.5 zu arbeiten oder so?
FlavorScape

1
Und Sie fragen sich, wie ich diese Funktion aufrufe, um Fenstergrößenänderungsereignisse zu empfangen? So geht's: addEvent (Fenster, "Größe ändern", Funktionsreferenz); :)
Oabarca

6
Beachten Sie, dass ab IE 11 attachEventnicht mehr unterstützt wird. Der bevorzugte Weg für die Zukunft ist addEventListener.
Luke

6
Sei vorsichtig mit elem == undefined. Es ist möglich (obwohl unwahrscheinlich), dass "undefiniert" lokal als etwas anderes definiert ist. stackoverflow.com/questions/8175673/…
Luke

32

Das Größenänderungsereignis sollte niemals direkt verwendet werden, da es während der Größenänderung kontinuierlich ausgelöst wird.

Verwenden Sie eine Entprellungsfunktion, um die überschüssigen Anrufe zu verringern.

window.addEventListener('resize',debounce(handler, delay, immediate),false);

Hier ist ein allgemeines Debounce, das im Netz herumschwirrt, aber suchen Sie nach fortgeschritteneren als featuerd in 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);
    };
};

Dies kann so verwendet werden ...

window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);

Es wird nie mehr als einmal alle 200 ms abgefeuert.

Für Änderungen der mobilen Ausrichtung verwenden Sie:

window.addEventListener('orientationchange', () => console.log('hello'), false);

Hier ist eine kleine Bibliothek, die ich zusammengestellt habe, um das ordentlich zu erledigen.


Ich schätze die Informationen zu: Debounce (es scheint jetzt ein unschätzbares Konzept / eine unschätzbare Funktion zu sein, obwohl ich mich zuvor geweigert habe, Timeouts auf diese Weise zu verwenden), Lodash (obwohl ich persönlich nicht überzeugt bin) und die Lösung der Unklarheit darüber, ob addEvent als Fallback verwendet werden soll zu addEventListener (nur weil ältere Antworten die Kommentare dazu nicht wirklich explizit ansprechen)
wunth

5
Zu Ihrer Information, da Sie die ES6-Pfeilfunktionsnotation verwenden, muss die innere Funktion (...arguments) => {...}(oder ...argsfür weniger Verwirrung) vorhanden sein, da die argumentsVariable ihren Gültigkeitsbereich nicht mehr verfügbar hat.
Coderatchet

Ich bin mir völlig bewusst, dass Snippet nicht mein Code ist, sondern nur ein Beispiel.
Frontsideup

Tolle Antwort, die Perf-Probleme mit der Größenänderung müssen behoben werden! Das Entprellen ist eine Option, eine andere ist das einfache Drosseln (was der richtige Weg sein kann, wenn Sie die Größe Ihrer Benutzeroberfläche in "Schritten" ändern müssen). Beispiele finden Sie unter bencentra.com/code/2015/02/27/optimizing-window-resize.html
Robin Métral,

24

Lösung für 2018+:

Sie sollten ResizeObserver verwenden . Es ist eine browser-native Lösung, die eine viel bessere Leistung bietet als die Verwendung des resizeEreignisses. Darüber hinaus unterstützt es nicht nur das Ereignis auf der, documentsondern auch auf beliebige 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);

Derzeit unterstützen dies Firefox, Chrome und Safari . Für andere (und ältere) Browser müssen Sie eine Polyfüllung verwenden .


Immer noch die beste Antwort im Jahr 2020 imo
Jesse Reza Khorasanee


16

Ich glaube, dass @Alex V bereits die richtige Antwort gegeben hat, aber die Antwort muss modernisiert werden, da sie jetzt über fünf Jahre alt ist.

Es gibt zwei Hauptprobleme:

  1. Niemals objectals Parametername verwenden. Es ist ein reserviertes Wort. Wenn dies gesagt wird, funktioniert die von @Alex V bereitgestellte Funktion nicht strict mode.

  2. Die addEventvon @Alex V bereitgestellte Funktion gibt nicht zurück, event objectwenn die addEventListenerMethode verwendet wird. addEventUm dies zu ermöglichen, sollte der Funktion ein weiterer Parameter hinzugefügt werden .

HINWEIS: Der neue Parameter to addEventwurde optional gemacht, damit durch die Migration auf diese neue Funktionsversion keine vorherigen Aufrufe dieser Funktion unterbrochen werden. Alle älteren Verwendungen werden unterstützt.

Hier ist die aktualisierte addEventFunktion mit diesen Änderungen:

/*
    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;
};

Ein Beispielaufruf für die neue addEventFunktion:

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);

Ich würde argumentieren, dass attachEvent 2017 nicht mehr relevant ist.
Vlad Nicula

@VladNicula Ich würde zustimmen, aber diese Antwort ist zwei Jahre alt.
WebWanderer

12

Vielen Dank, dass Sie auf meinen Blog-Beitrag unter http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html verwiesen haben .

Während Sie sich einfach mit dem Standardereignis zum Ändern der Fenstergröße verbinden können, werden Sie feststellen, dass das Ereignis im IE einmal für jede X- und einmal für jede Y-Achsenbewegung ausgelöst wird, was dazu führt, dass eine Menge Ereignisse ausgelöst werden, die möglicherweise eine Leistung haben Auswirkungen auf Ihre Website, wenn das Rendern eine intensive Aufgabe ist.

Meine Methode beinhaltet eine kurze Zeitüberschreitung, die bei nachfolgenden Ereignissen abgebrochen wird, damit das Ereignis nicht in Ihren Code gesprudelt wird, bis der Benutzer die Größe des Fensters geändert hat.


7
window.onresize = function() {
    // your code
};

22
Wie viele der obigen Kommentare sagen, ist es am besten, die Onresize-Funktion nicht zu überschreiben. füge lieber ein neues Ereignis hinzu. Siehe Jondlms Antwort.
Luke


2

Die oben bereits erwähnten Lösungen funktionieren, wenn Sie nur die Größe des Fensters und des Fensters ändern möchten. Wenn Sie jedoch möchten, dass die Größenänderung an untergeordnete Elemente weitergegeben wird, müssen Sie das Ereignis selbst weitergeben. Hier ist ein Beispielcode dafür:

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);
});

Beachten Sie, dass ein untergeordnetes Element aufrufen kann

 event.preventDefault();

für das Ereignisobjekt, das als erstes Arg des Größenänderungsereignisses übergeben wird. Zum Beispiel:

var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
  ...
  event.preventDefault();
});

1
<script language="javascript">
    window.onresize = function() {
    document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
} 

</script>

1
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_];
        }
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.