Backbone: navigasi() dengan spasi di url memicu rute bahkan ketika {trigger:false} di Firefox

Dibuat pada 27 Nov 2014  ·  8Komentar  ·  Sumber: jashkenas/backbone

Pertimbangkan contoh ini:

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

Ini harus mencatat "rute rumah: null" dan kemudian melanjutkan untuk mencatat "klik #" untuk setiap klik pada "Klik saya".

Sekarang, buat satu modifikasi kecil. Tambahkan spasi ke url di navigasi():

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

Coba lagi dan Anda akan menemukan bahwa "rute asal: #" juga akan mulai dicatat, dan penghitung akan mengatur ulang _dua dari setiap tiga klik_.

Ini dalam rilis 1.1.2 dan saya menguji pada Firefox 33.1 terbaru. Saya tidak mengalami masalah ini di Chrome - bisa jadi karena Chrome mungkin melakukan sesuatu untuk menyandikan spasi di URL. Aku tidak yakin.

Saya menyadari bahwa karakter spasi seharusnya tidak ada di URL sejak awal, tetapi perilaku ini aneh dan setidaknya harus didokumentasikan. (yaitu "Navigasi() mungkin tidak berperilaku seperti yang diharapkan dengan URL yang berisi spasi (atau karakter tidak aman lainnya??).")

Saya tidak yakin apakah ada perbaikan yang mudah untuk ini, tetapi saya harap setidaknya dengan mendokumentasikan bug ini, saya menghemat waktu pengembang lain untuk mencoba memburunya.

invalid

Komentar yang paling membantu

Inilah yang saya temukan. Di Firefox, jika Anda mencentang variabel "this.location.href", spasi putih apa pun dalam variabel dikodekan ke dalam %20. Chrome (dan mungkin IE) membiarkannya sebagai spasi. Ini adalah masalah di Backbone, karena saat Anda menavigasi, "checkUrl()" melakukan perbandingan "this.fragment" dengan nilai yang dikembalikan dari "this.getFragment()" untuk menentukan apakah akan memanggil "this.getFragment()" atau tidak. loadUrl()", jika tidak cocok. this.getFragment() mengembalikan nilai this.location.href, dengan %20 menggantikan spasi apa pun di Firefox (atau pengkodean apa pun dalam hal ini). this.fragment mengembalikan setara yang didekodekan. this.fragment tetap diterjemahkan, terlepas dari apakah Anda menggunakan encodeURI() pada URL Anda atau tidak, karena dalam fungsi "navigate()", this.fragment ditetapkan dengan memanggil "this.decodeFragment()" pada URL yang diteruskan di, menghapus segala upaya untuk memaksa penyandian.

Oleh karena itu, jika this.fragment selalu merupakan URL yang didekode karena penggunaan this.decodeFragment(), dan URL berisi karakter apa pun yang akan diubah oleh encodeURI() (dalam hal ini spasi), itu tidak akan pernah cocok dengan nilai yang dikembalikan ini .getFragment() di Firefox, karena Firefox mengkodekan nilai this.location.href, sedangkan browser lain tidak. Karena kedua nilai ini tidak cocok, this.loadUrl() dipanggil di checkUrl(), terlepas dari apakah parameter pemicu di router.navigate benar atau salah.

Perbaikan awal (pengujian pra-lengkap) adalah mengubah nilai pengembalian metode "getHash()" menjadi:

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

Semua 8 komentar

Hai @chaimpeck! Terima kasih telah melaporkan ini.

Sayangnya, saya tidak dapat mereproduksinya menggunakan kode di atas. Saya mencoba Chrome dan Firefox terbaru dengan cabang master dan rilis 1.1.2. Maukah Anda memposting contoh kerja di Gist/bin/fiddle yang bisa saya lihat?

Kami pasti pernah mengalami masalah dengan encoding/decoding karakter tertentu di Firefox sebelumnya dan saya tidak ragu ada lagi. :senyum:

Saya sebenarnya telah melihat masalah yang sama persis ini, tetapi saya tidak dapat membagikan kode saya. Saya akan melihat apakah saya dapat meniru beberapa kode pengujian untuk mereplikasi ini, tetapi saya telah menemukan bahwa masalahnya pasti berbasis browser. Semua versi modern IE dan Chrome berfungsi dengan baik, tetapi setidaknya di Firefox v31.5.0 (jangan tanya, saya benci infrastruktur tempat kita terjebak), itu pasti memicu bahkan tanpa menambahkan opsi pemicu.

Inilah yang saya temukan. Di Firefox, jika Anda mencentang variabel "this.location.href", spasi putih apa pun dalam variabel dikodekan ke dalam %20. Chrome (dan mungkin IE) membiarkannya sebagai spasi. Ini adalah masalah di Backbone, karena saat Anda menavigasi, "checkUrl()" melakukan perbandingan "this.fragment" dengan nilai yang dikembalikan dari "this.getFragment()" untuk menentukan apakah akan memanggil "this.getFragment()" atau tidak. loadUrl()", jika tidak cocok. this.getFragment() mengembalikan nilai this.location.href, dengan %20 menggantikan spasi apa pun di Firefox (atau pengkodean apa pun dalam hal ini). this.fragment mengembalikan setara yang didekodekan. this.fragment tetap diterjemahkan, terlepas dari apakah Anda menggunakan encodeURI() pada URL Anda atau tidak, karena dalam fungsi "navigate()", this.fragment ditetapkan dengan memanggil "this.decodeFragment()" pada URL yang diteruskan di, menghapus segala upaya untuk memaksa penyandian.

Oleh karena itu, jika this.fragment selalu merupakan URL yang didekode karena penggunaan this.decodeFragment(), dan URL berisi karakter apa pun yang akan diubah oleh encodeURI() (dalam hal ini spasi), itu tidak akan pernah cocok dengan nilai yang dikembalikan ini .getFragment() di Firefox, karena Firefox mengkodekan nilai this.location.href, sedangkan browser lain tidak. Karena kedua nilai ini tidak cocok, this.loadUrl() dipanggil di checkUrl(), terlepas dari apakah parameter pemicu di router.navigate benar atau salah.

Perbaikan awal (pengujian pra-lengkap) adalah mengubah nilai pengembalian metode "getHash()" menjadi:

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

Masih diperlukan dengan versi terakhir jadi terima kasih!

Saya memiliki masalah yang sama ketika mencoba menggunakan karakter non-standar di URL, dalam kasus saya ö (karakter yang ada dalam alfabet Swedia). Versi terbaru dari Chrome dan Backbone.

solusi sjmiller85 bekerja untuk saya juga. Terima kasih banyak!

@ sjmiller85 Apa solusi Anda di sini? Saya tidak sepenuhnya mengerti apa yang harus digunakan untuk 'pathStripper'. Apakah ini regex?
Sunting: ini berfungsi dalam situasi saya. lihat https://github.com/jashkenas/backbone/pull/3955/files
getHash: function (t) { var e = (t || this).location.href.match(/#(.*)$/); return e ? e[1] : "" }

@Aggror pathStripper adalah, menurut dokumentasi, regex yang di-cache untuk menghapus url hash.

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

Jadi ini setara dengan solusi Anda, hanya lebih rapi dan efisien :)

hindari menambahkan hash yang sama secara simultan ke router Anda dan juga jaga kondisi awal, saya akan menunjukkan kode kepada Anda
(untuk menangani kasus awal) (untuk mencegah penambahan rute yang sama secara simultan)
if ( route.length === 1 || route[routes.length-1] === getHash() ) {
kembali salah;
}
lain{
route.push(getHash())
};

Apakah halaman ini membantu?
0 / 5 - 0 peringkat