Backbone: navegar () con un espacio en la url activa la ruta incluso cuando {disparador: falso} en Firefox

Creado en 27 nov. 2014  ·  8Comentarios  ·  Fuente: jashkenas/backbone

Considere este ejemplo:

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

Esto debería registrar "ruta de inicio: nulo" y luego proceder a registrar "haga clic en #" por cada clic en "Haga clic en mí".

Ahora, haz una pequeña modificación. Agregue un espacio a la URL en navegar ():

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

Vuelva a intentarlo y verá que esa "ruta de origen: #" también comenzará a registrarse, y el contador se reiniciará _dos de cada tres clics_.

Esto está en la versión 1.1.2 y estoy probando en el último Firefox 33.1. No tengo este problema en Chrome; podría deberse a que Chrome tal vez hace algo para codificar espacios en la URL. Aunque no estoy seguro.

Me doy cuenta de que, en primer lugar, el carácter de espacio no debería estar en una URL, pero este comportamiento es extraño y, como mínimo, debería documentarse. (es decir, "Navegar() puede no comportarse como se esperaba con direcciones URL que contienen espacios (u otros caracteres no seguros).")

No estoy seguro de si hay una solución fácil para esto, pero espero que al menos al documentar este error ahorre tiempo a otros desarrolladores para tratar de encontrarlo.

invalid

Comentario más útil

Esto es lo que he descubierto. En Firefox, si marca la variable "this.location.href", cualquier espacio en blanco en la variable se codifica en %20's. Chrome (y presumiblemente IE) los deja como espacios en blanco. Este es un problema en Backbone, ya que cuando vas a navegar, "checkUrl()" hace una comparación de "this.fragment" con el valor devuelto de "this.getFragment()" para determinar si llamar o no a "this. loadUrl()", si no coinciden. this.getFragment() devuelve el valor de this.location.href, con los %20 en lugar de cualquier espacio en Firefox (o cualquier codificación para el caso). this.fragment devuelve un equivalente decodificado. this.fragment permanece decodificado, independientemente de si usa o no encodeURI() en sus URL, porque en la función "navegar()", this.fragment se asigna llamando a "this.decodeFragment()" en la URL que se pasa en, eliminando cualquier intento de forzar la codificación.

Por lo tanto, si this.fragment es siempre una URL decodificada debido al uso de this.decodeFragment(), y la URL contiene caracteres que cambiaría encodeURI() (en este caso, espacios), nunca coincidirá con el valor devuelto de this. .getFragment() en Firefox, ya que Firefox codifica el valor de this.location.href, mientras que otros navegadores no lo hacen. Dado que estos dos valores no coinciden, se llama a this.loadUrl() en checkUrl(), independientemente de si el parámetro de activación en router.navigate es verdadero o falso.

La solución preliminar (prueba previa exhaustiva) sería cambiar el valor de retorno del método "getHash()" para leer:

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

Todos 8 comentarios

¡Hola @chaimpeck! Gracias por informar esto.

Desafortunadamente, no pude reproducirlo usando el código anterior. Probé los últimos Chrome y Firefox tanto con la rama principal como con la versión 1.1.2. ¿Le importaría publicar un ejemplo de trabajo en un gist/bin/fiddle que pueda ver?

Definitivamente hemos tenido problemas antes con la codificación/descodificación de caracteres específicos en Firefox y no dudo que haya más. :smiley:

De hecho, he visto exactamente el mismo problema, pero no puedo compartir mi código. Veré si puedo simular un código de prueba para replicar esto, pero descubrí que el problema definitivamente se basa en el navegador. Todas las versiones modernas de IE y Chrome funcionan bien, pero al menos en Firefox v31.5.0 (no preguntes, odio la infraestructura en la que estamos atascados), definitivamente se activa sin siquiera agregar la opción de activación.

Esto es lo que he descubierto. En Firefox, si marca la variable "this.location.href", cualquier espacio en blanco en la variable se codifica en %20's. Chrome (y presumiblemente IE) los deja como espacios en blanco. Este es un problema en Backbone, ya que cuando vas a navegar, "checkUrl()" hace una comparación de "this.fragment" con el valor devuelto de "this.getFragment()" para determinar si llamar o no a "this. loadUrl()", si no coinciden. this.getFragment() devuelve el valor de this.location.href, con los %20 en lugar de cualquier espacio en Firefox (o cualquier codificación para el caso). this.fragment devuelve un equivalente decodificado. this.fragment permanece decodificado, independientemente de si usa o no encodeURI() en sus URL, porque en la función "navegar()", this.fragment se asigna llamando a "this.decodeFragment()" en la URL que se pasa en, eliminando cualquier intento de forzar la codificación.

Por lo tanto, si this.fragment es siempre una URL decodificada debido al uso de this.decodeFragment(), y la URL contiene caracteres que cambiaría encodeURI() (en este caso, espacios), nunca coincidirá con el valor devuelto de this. .getFragment() en Firefox, ya que Firefox codifica el valor de this.location.href, mientras que otros navegadores no lo hacen. Dado que estos dos valores no coinciden, se llama a this.loadUrl() en checkUrl(), independientemente de si el parámetro de activación en router.navigate es verdadero o falso.

La solución preliminar (prueba previa exhaustiva) sería cambiar el valor de retorno del método "getHash()" para leer:

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

Todavía se necesita con la última versión, ¡así que gracias!

Tengo el mismo problema cuando trato de usar caracteres no estándar en la URL, en mi caso åäö (caracteres que están en el alfabeto sueco). Última versión de Chrome y Backbone.

La solución de sjmiller85 también funcionó para mí. ¡Gracias un montón!

@ sjmiller85 ¿Cuál fue su solución aquí? No entiendo completamente qué se debe usar para 'pathStripper'. ¿Es esto una expresión regular?
Editar: esto funciona en mi situación. ver https://github.com/jashkenas/backbone/pull/3955/files
getHash: function (t) { var e = (t || this).location.href.match(/#(.*)$/); return e ? e[1] : "" }

@Aggror pathStripper es, según la documentación, una expresión regular almacenada en caché para eliminar URL de hash.

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

Entonces es el equivalente de su solución, solo que más ordenada y eficiente :)

evite agregar el mismo hash simultáneo a su enrutador y también cuide la condición inicial, le mostraré un código
(para manejar el caso inicial) (para evitar agregar las mismas rutas simultáneas)
if ( rutas.longitud === 1 || rutas[rutas.longitud-1] === getHash() ) {
falso retorno;
}
demás{
rutas.push(getHash())
};

¿Fue útil esta página
0 / 5 - 0 calificaciones