Backbone: navigation() mit einem Leerzeichen in der URL löst die Route aus, selbst wenn {trigger:false} in Firefox

Erstellt am 27. Nov. 2014  ·  8Kommentare  ·  Quelle: jashkenas/backbone

Betrachten Sie dieses Beispiel:

$(function(){
var AppRouter = Backbone.Router.extend({

    routes: {
        '(count/:count)': 'home',
    },

    home: function(currCount) {
        var counter = 0;
        var thisObj = this;

        $("body").html($("<p>Click me</p>").on('click', function() {
            console.log("clicked "+counter);
            counter++;
            thisObj.navigate('count/'+counter, {trigger:false, replace: true});
        }));

        console.log('home route: '+currCount);    
    },
});

window.app = new AppRouter();
Backbone.history.start();
});

Dies sollte "home route: null" protokollieren und dann fortfahren, "click #" für jeden Klick auf "Click me" zu protokollieren.

Nehmen Sie jetzt eine kleine Änderung vor. Fügen Sie der URL in Navigieren () ein Leerzeichen hinzu:

thisObj.navigate('count/ '+counter, {trigger:false, replace: true});

Versuchen Sie es erneut, und Sie werden feststellen, dass diese "Homeroute: #" ebenfalls protokolliert wird und der Zähler _zwei von drei Klicks_ zurücksetzt.

Dies ist in der Version 1.1.2 und ich teste auf dem neuesten Firefox 33.1. Ich habe dieses Problem nicht in Chrome - es könnte daran liegen, dass Chrome möglicherweise etwas tut, um Leerzeichen in der URL zu codieren. Ich bin mir aber nicht sicher.

Mir ist klar, dass das Leerzeichen eigentlich gar nicht in einer URL stehen sollte, aber dieses Verhalten ist merkwürdig und sollte zumindest dokumentiert werden. (dh "Navigation() verhält sich bei URLs mit Leerzeichen (oder anderen unsicheren Zeichen??) möglicherweise nicht wie erwartet.")

Ich bin mir nicht sicher, ob es dafür eine einfache Lösung gibt, aber ich hoffe, dass ich zumindest durch die Dokumentation dieses Fehlers anderen Entwicklern Zeit erspare, ihn zu finden.

invalid

Hilfreichster Kommentar

Hier ist, was ich entdeckt habe. Wenn Sie in Firefox die Variable "this.location.href" überprüfen, werden alle Leerzeichen in der Variablen in %20 kodiert. Chrome (und vermutlich IE) lässt sie als Leerzeichen. Dies ist ein Problem in Backbone, da „checkUrl()“ beim Navigieren einen Vergleich von „this.fragment“ mit dem zurückgegebenen Wert von „this.getFragment()“ durchführt, um zu bestimmen, ob „this.fragment“ aufgerufen werden soll oder nicht. loadUrl()", wenn sie nicht übereinstimmen. this.getFragment() gibt den Wert von this.location.href zurück, wobei die %20 anstelle von Leerzeichen in Firefox (oder allen Codierungen für diese Angelegenheit) stehen. this.fragment gibt ein decodiertes Äquivalent zurück. this.fragment bleibt decodiert, unabhängig davon, ob Sie encodeURI() für Ihre URLs verwenden oder nicht, denn in der Funktion „navigate()“ wird this.fragment zugewiesen, indem „this.decodeFragment()“ für die übergebene URL aufgerufen wird in, Entfernen aller Versuche, die Codierung zu erzwingen.

Wenn also this.fragment aufgrund der Verwendung von this.decodeFragment() immer eine decodierte URL ist und die URL Zeichen enthält, die encodeURI() ändern würde (in diesem Fall Leerzeichen), wird sie niemals mit dem zurückgegebenen Wert von this übereinstimmen .getFragment() in Firefox, da Firefox den Wert von this.location.href codiert, während andere Browser dies nicht tun. Da diese beiden Werte nicht übereinstimmen, wird this.loadUrl() in checkUrl() aufgerufen, unabhängig davon, ob der Triggerparameter in router.navigate wahr oder falsch ist.

Die vorläufige Lösung (vorerschöpfende Tests) wäre, den Rückgabewert der Methode "getHash()" zu ändern, um zu lesen:

return match ? this.decodeFragment(match[1].replace(pathStripper, '')) : '';

Alle 8 Kommentare

Hallo @chaimpeck! Danke, dass du das gemeldet hast.

Leider konnte ich es mit obigem Code nicht reproduzieren. Ich habe den neuesten Chrome und Firefox sowohl mit dem Master-Zweig als auch mit der Version 1.1.2 ausprobiert. Würde es Ihnen etwas ausmachen, ein funktionierendes Beispiel in einem Gist/Bin/Fiddle zu posten, das ich mir ansehen kann?

Wir hatten definitiv schon früher Probleme mit der Codierung/Decodierung bestimmter Zeichen in Firefox und ich würde nicht bezweifeln, dass es noch mehr gibt. :smiley:

Ich habe tatsächlich genau dasselbe Problem gesehen, kann aber meinen Code nicht teilen. Ich werde sehen, ob ich einen Testcode nachbauen kann, um dies zu replizieren, aber ich habe festgestellt, dass das Problem definitiv browserbasiert ist. Alle modernen Versionen von IE und Chrome funktionieren gut, aber zumindest auf Firefox v31.5.0 (fragen Sie nicht, ich hasse die Infrastruktur, auf der wir festsitzen), wird es definitiv ausgelöst, ohne die Trigger-Option hinzuzufügen.

Hier ist, was ich entdeckt habe. Wenn Sie in Firefox die Variable "this.location.href" überprüfen, werden alle Leerzeichen in der Variablen in %20 kodiert. Chrome (und vermutlich IE) lässt sie als Leerzeichen. Dies ist ein Problem in Backbone, da „checkUrl()“ beim Navigieren einen Vergleich von „this.fragment“ mit dem zurückgegebenen Wert von „this.getFragment()“ durchführt, um zu bestimmen, ob „this.fragment“ aufgerufen werden soll oder nicht. loadUrl()", wenn sie nicht übereinstimmen. this.getFragment() gibt den Wert von this.location.href zurück, wobei die %20 anstelle von Leerzeichen in Firefox (oder allen Codierungen für diese Angelegenheit) stehen. this.fragment gibt ein decodiertes Äquivalent zurück. this.fragment bleibt decodiert, unabhängig davon, ob Sie encodeURI() für Ihre URLs verwenden oder nicht, denn in der Funktion „navigate()“ wird this.fragment zugewiesen, indem „this.decodeFragment()“ für die übergebene URL aufgerufen wird in, Entfernen aller Versuche, die Codierung zu erzwingen.

Wenn also this.fragment aufgrund der Verwendung von this.decodeFragment() immer eine decodierte URL ist und die URL Zeichen enthält, die encodeURI() ändern würde (in diesem Fall Leerzeichen), wird sie niemals mit dem zurückgegebenen Wert von this übereinstimmen .getFragment() in Firefox, da Firefox den Wert von this.location.href codiert, während andere Browser dies nicht tun. Da diese beiden Werte nicht übereinstimmen, wird this.loadUrl() in checkUrl() aufgerufen, unabhängig davon, ob der Triggerparameter in router.navigate wahr oder falsch ist.

Die vorläufige Lösung (vorerschöpfende Tests) wäre, den Rückgabewert der Methode "getHash()" zu ändern, um zu lesen:

return match ? this.decodeFragment(match[1].replace(pathStripper, '')) : '';

Wird noch mit der letzten Version benötigt, also danke!

Ich habe das gleiche Problem, wenn ich versuche, nicht standardmäßige Zeichen in der URL zu verwenden, in meinem Fall åäö (Zeichen im schwedischen Alphabet). Neueste Version von Chrome und Backbone.

Die Lösung von sjmiller85 hat auch bei mir funktioniert. Vielen Dank!

@sjmiller85 Was war hier deine Lösung? Ich verstehe nicht ganz, was für 'pathStripper' verwendet werden soll. Ist das eine Regex?
Bearbeiten: Dies funktioniert in meiner Situation. siehe https://github.com/jashkenas/backbone/pull/3955/files
getHash: function (t) { var e = (t || this).location.href.match(/#(.*)$/); return e ? e[1] : "" }

@Aggror pathStripper ist laut Dokumentation eine zwischengespeicherte Regex zum Entfernen von Hash-URLs.

// Cached regex for stripping urls of hash.
var pathStripper = /#.*$/;

Es ist also das Äquivalent Ihrer Lösung, nur ordentlicher und effizienter :)

Vermeiden Sie es, Ihrem Router gleichzeitig denselben Hash hinzuzufügen, und kümmern Sie sich auch um die Anfangsbedingung. Ich zeige Ihnen einen Code
(um den Anfangsfall zu behandeln) (um zu verhindern, dass gleichzeitig dieselben Routen hinzugefügt werden)
if (routen.länge === 1 || routen[routen.länge-1] === getHash() ) {
falsch zurückgeben;
}
anders{
routen.push(getHash())
};

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen