Frage

Die SetTimeout -Funktion scheint mir immer Probleme zu geben. Im Moment habe ich eine Funktion, die rekursiv ist (ruft sich durch SetTimeout) und ändert die Höhe der Elemente.

Die Funktion wird zwei Argumente gesendet: das Element zu verändern und die Elemente maximale Höhe. Der Zweck der Funktion besteht darin, das Element zu entfalten oder in konstantem Tempo nach unten zu "rutschen". Ich bin mir bewusst, dass ich dieses Problem wahrscheinlich mit JQuery lösen könnte, aber ich versuche meine eigene Funktion.

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    {
        var factor = 10;
        var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
        element.style.height = new_height + 'px';

        var func_call = 'slide_down(' + element + ', ' + max_height + ');';
        window.setTimeout(func_call, 10);
    }
}

Ich habe die Argumente getestet, wenn die Funktion ursprünglich aufgerufen wird. max_height ist auf 20 gesetzt, da es sich um die gewünschte Elemente handelt (ich habe diesen Wert von .ScrollHeight erhalten).

Wenn die Funktion erledigt ist, möchte ich, dass sie sich selbst aufruft, bis max_height die Höhe des Elements ist. Ich mache das mit diesem SetTimeout -Anruf:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);

Und es funktioniert nicht. Das funktioniert:

var func_call = 'alert(1);';
window.setTimeout(func_call, 10);

Ich habe auch versucht, den Funktionsaufruf direkt in die SetTimeout -Anweisung einzulegen, funktioniert immer noch nicht.

Beachten Sie, dass die Höhe des Elements die erste Iteration ändert, die Funktion nennt sich einfach nie. Daher wird die Elementvariable korrekt eingestellt, und ich habe Alert () verwendet, um das ebenfalls korrekte max_height anzuzeigen.

alert(func_call);

Alarmiert dies:

slide_down([object HTMLParagraphElement], 20);
War es hilfreich?

Lösung

Wenn Sie das tun:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';

Sie konvertieren Element in eine Zeichenfolge, sodass Ihre Zeitüberschreitung so aussieht

slide_down("[Object]", 100);

was offensichtlich nicht funktionieren wird.

Was Sie tun sollten, ist eine Schließung zu erstellen - es ist etwas kompliziert, aber im Grunde erstellen Sie eine Funktion, und die lokale Variable aus der alten Funktion sind in der neuen Funktion weiterhin verfügbar.

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    {
        var factor = 10;
        var new_height = (element.clientHeight + factor >= max_height) ? max_height : (element.clientHeight + factor);
        element.style.height = new_height + 'px';

        var func = function()
        {
            slide_down(element, max_height);
        }

        window.setTimeout(func, 10);
    }
}

Auch 10 ist für eine Zeitüberschreitung etwas kurz - ich würde empfehlen, mindestens 50 zu verwenden.

Andere Tipps

Zunächst einmal: "Im Moment habe ich eine Funktion, die rekursiv ist (ruft sich durch SetTimeout)" schreit setInterval Für mich, wenn Sie die Zeit nicht variieren.

Zweitens liegt dies daran, dass die Elementreferenz in der Stringconat als element.toString () [Objekt] verloren geht. Versuchen Sie, eine ID zu übergeben, die Sie neu finden können, eine Referenz A Level-Up-Stufe speichern oder (wie ich gerade gesehen habe, dass Matt B darauf hinweist) das erweiterte Methodenformular.

Eine subtilere Art, die Methode zu schreiben (als Erweiterung der Gregs -Antwort):

function slide_down(element, max_height)
{   
    if(element.clientHeight < max_height)
    { return; }

    var factor = 10,
        new_height = element.clientHeight + factor,
        f = arguments.callee;

    if( new_height > max_height )
    { new_height = max_height; }

    element.style.height = new_height + 'px';

    window.setTimeout(function() { f(element, max_height); }, 10);
}

Der eigentliche Vorteil dieses Beispielcode ist die Verwendung von arguments.callee. Auf diese Weise werden Sie Ihre Funktion nicht brechen, falls Sie sich entscheiden, sie umzubenennen. Ich habe auch einfach die new_height Wert zuweisen. Das Problem im alten Code ist, dass Sie durchgeführt wurden element.clientHeight + factor zweimal, was irgendwie Unnessary ist. Nicht, dass es in diesem Fall einen erkennbaren Einfluss auf Ihre Leistung hat. Aber es ist immer gut, vermeiden, dasselbe immer wieder die gleichen Dinge zu berechnen, aber nur das Ergebnis für die spätere Verwendung zu speichern.

Ich hatte eine ähnliche Erfahrung. Wenn Sie das nächste Mal das Element übergeben, wird es in eine Zeichenfolge im Funktionsaufruf konvertiert. Wenn die Funktion ausgeführt wird, versucht sie, ein Element namens [Objekt] zu finden oder so etwas, anstatt von dem, was Sie beabsichtigt haben.

Ändern Sie Ihren Funktionsparameter, um die ID des Elements zu nehmen, und machen Sie ein Dokument.

Das Problem mit Ihrem Code ist, dass Sie den Parameter Element nicht übergeben können.

Anstatt von:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';

window.setTimeout(func_call, 10);

Versuchen Sie, anonyme Funktionen zu verwenden:

window.setTimeout(function() {
    slide_down(element, max_height)
}, 10);

@Matt.b: Argumente, die in SetTimeout -Anruf übergehen (so wie Sie es tun), wird in IE nicht unterstützt.

Zwei Dinge:

1. Es gibt eine alternative Möglichkeit, anzurufen setTimeout() in dem Sie die Funktion und Parameter übergeben, anstatt eine String, die ausgeführt werden soll. In der Tat, Die Gecko Dom -Handbuchzustände dass Ihre Version des Anrufs setTimeout() ist nicht zu empfehlen.

Anstatt von:

var func_call = 'slide_down(' + element + ', ' + max_height + ');';
window.setTimeout(func_call, 10);

Versuchen Sie es stattdessen:

window.setTimeout(slide_down, 10, element, max_height);  

Aktualisieren: Wie Roborg erwähnt, funktioniert dies möglicherweise nicht in IE, also können Sie es genauso gut ignorieren.


2. Ich habe das Gefühl, dass ich anrufen kann setTimeout() von innerhalb einer Funktion, die sich selbst genannt wurde setTimeout() ist entweder nicht erlaubt oder funktioniert nicht gut. Ich gehe davon aus, dass Sie die Anrufe wie diese verkettet, weil der Code wiederholt ausgeführt wird? Wenn ja, das ist was, was window.setInterval() ist für.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top