Mengubah string kueri tanpa memuat ulang halaman

114

Saya membuat galeri foto, dan ingin mengubah string dan judul kueri saat foto-foto itu diramban.

Perilaku yang saya cari sering terlihat dengan beberapa implementasi halaman berkelanjutan / tak terbatas, di mana saat Anda menggulir ke bawah, string kueri terus menambah nomor halaman ( http://x.com?page=4 ) dll .. Ini seharusnya sederhana dalam teori, tapi saya ingin sesuatu yang aman di browser utama.

Saya menemukan postingan yang bagus ini , dan mencoba mengikuti contoh dengan window.history.pushstate, tetapi sepertinya tidak berhasil untuk saya. Dan saya tidak yakin apakah itu ideal karena saya tidak terlalu peduli tentang mengubah riwayat browser.

Saya hanya ingin menawarkan kemampuan untuk menandai foto yang sedang dilihat, tanpa memuat ulang halaman setiap kali foto diubah.

Berikut adalah contoh halaman tak terbatas yang mengubah string kueri: http://tumbledry.org/

UPDATE menemukan metode ini:

window.location.href = window.location.href + '#abc';

tampaknya berfungsi untuk saya, tetapi saya menggunakan chrome baru .. mungkin akan menyebabkan beberapa masalah dengan browser lama?

Sonic Soul
sumber
Dapatkah Anda memposting tautan ke beberapa situs contoh yang memperbarui string kuerinya secara dinamis? Saya tidak berpikir itu bisa dilakukan, tetapi Anda dapat mengubah nilai hash dan itu mungkin cukup untuk mendapatkan apa yang Anda inginkan.
Pointy
kemungkinan duplikat Mengapa web baru Dropbox dapat mengubah URL tanpa penyegaran halaman? dan tiga pertanyaan itu ditandai sebagai duplikat dari
Quentin
@Tokopedia Anda hanya dapat memiliki satu suara lebih dekat ...:)
gdoron mendukung Monica

Jawaban:

185

Jika Anda mencari modifikasi Hash, solusi Anda berfungsi dengan baik. Namun, jika Anda ingin mengubah kueri, Anda dapat menggunakan pushState, seperti yang Anda katakan. Ini adalah contoh yang mungkin membantu Anda menerapkannya dengan benar. Saya menguji dan itu bekerja dengan baik:

if (history.pushState) {
    var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?myNewUrlQuery=1';
    window.history.pushState({path:newurl},'',newurl);
}

Ini tidak memuat ulang halaman, tetapi hanya memungkinkan Anda untuk mengubah kueri URL. Anda tidak akan dapat mengubah protokol atau nilai host. Dan tentunya membutuhkan browser modern yang bisa mengolah HTML5 History API.

Untuk informasi lebih lanjut:

http://diveintohtml5.info/history.html

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history

Fabio Nolasco
sumber
6
Saya percaya Anda dapat mempersingkat window.location.protocol + '//' + window.location.hosthanya: window.location.origin.
Garrett
4
Selain itu, untuk sedikit info tambahan, jalur relatif juga berfungsi dengan history.pushState(). Tidak ada stateargumen sebenarnya yang dibutuhkan. Keduanya berarti Anda dapat melakukan sesuatu yang sederhana seperti history.pushState(null, '', '/foo?bar=true')jika url baru Anda ada di host / port yang sama.
Blaskovicz
23
Perhatikan bahwa, jika Anda tidak ingin status baru muncul di riwayat browser, Anda dapat menggunakan history.replaceState()dengan argumen yang sama.
Blackus
6
GUNAKAN history.replaceState () jika tidak Anda perlu mengklik tombol KEMBALI dua kali di browser Anda
Zhenya
4
di peramban modern Anda dapat melakukan:if (window.history.pushState) { const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState({ path: newURL.href }, '', newURL.href); }
Allan Baptista
8

Berdasarkan jawaban Fabio, saya membuat dua fungsi yang mungkin berguna bagi siapa pun yang tersandung pada pertanyaan ini. Dengan dua fungsi ini, Anda dapat memanggil insertParam()dengan kunci dan nilai sebagai argumen. Ini akan menambahkan parameter URL atau, jika parameter kueri sudah ada dengan kunci yang sama, itu akan mengubah parameter itu ke nilai baru:

//function to remove query params from a URL
function removeURLParameter(url, parameter) {
    //better to use l.search if you have a location/link object
    var urlparts= url.split('?');   
    if (urlparts.length>=2) {

        var prefix= encodeURIComponent(parameter)+'=';
        var pars= urlparts[1].split(/[&;]/g);

        //reverse iteration as may be destructive
        for (var i= pars.length; i-- > 0;) {    
            //idiom for string.startsWith
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  
                pars.splice(i, 1);
            }
        }

        url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
        return url;
    } else {
        return url;
    }
}

//function to add/update query params
function insertParam(key, value) {
    if (history.pushState) {
        // var newurl = window.location.protocol + "//" + window.location.host + search.pathname + '?myNewUrlQuery=1';
        var currentUrlWithOutHash = window.location.origin + window.location.pathname + window.location.search;
        var hash = window.location.hash
        //remove any param for the same key
        var currentUrlWithOutHash = removeURLParameter(currentUrlWithOutHash, key);

        //figure out if we need to add the param with a ? or a &
        var queryStart;
        if(currentUrlWithOutHash.indexOf('?') !== -1){
            queryStart = '&';
        } else {
            queryStart = '?';
        }

        var newurl = currentUrlWithOutHash + queryStart + key + '=' + value + hash
        window.history.pushState({path:newurl},'',newurl);
    }
}
jmona789
sumber
bagaimana fungsi Anda lebih baik daripada new URLSearchParams()dengan metode aslinya sebagai set dan hapus ? dalam kedua kasus kita harus memasukkannya ke dalam sejarah denganhistory.pushState()
AlexNikonov
1
new URLSearchParams()tidak didukung oleh versi IE mana pun
jmona789
Terima kasih @ jmona789 ini bekerja dengan sempurna untuk saya dan persis seperti yang saya cari
mknopf
7

Saya telah menggunakan pustaka JavaScript berikut dengan sangat sukses:

https://github.com/balupton/jquery-history

Ini mendukung API riwayat HTML5 serta metode fallback (menggunakan #) untuk browser lama.

Library ini pada dasarnya adalah polyfill di sekitar `history.pushState '.

Ian Newson
sumber
luar biasa! apakah Anda mengujinya dengan semua browser ??
Sonic Soul
Implementasi saya telah diuji di IE7 +, Firefox 3.6+, Safari 5 dan Chrome 16+. Ini mungkin berfungsi dengan browser lain juga, tetapi saya tidak memiliki keluhan di beberapa sistem yang digunakan menggunakannya.
Ian Newson
Bagus. jadi sekarang .. cukup beri # alih-alih & saat menulis ke window.location.href bekerja untuk saya. karena tidak memuat ulang halaman. saya yakin itu akan rusak setelah saya mengujinya di IE .. pada titik mana saya akan pergi dengan perpustakaan yang Anda sarankan. terima kasih
Sonic Soul
Metode # adalah metode yang bagus karena memiliki dukungan browser yang sangat luas. Segalanya bisa menjadi rumit ketika Anda perlu memasukkan informasi itu dalam permintaan ke server, karena bagian # dari URL tidak dikirim oleh browser. Ada beberapa cara untuk itu, termasuk perpustakaan yang saya rujuk. Selain itu, menggunakan API riwayat HTML5 membantu membuat URL Anda lebih pendek secara keseluruhan dan membutuhkan lebih sedikit pekerjaan sisi klien untuk memulihkan status.
Ian Newson
Metode # juga bermasalah untuk berbagi media sosial; Twitter, Facebook, dan mungkin lainnya tidak bermain baik dengan tag anchor saat membuat pratinjau atau tautan kembali ke share.
mirth23
5

Saya ingin meningkatkan jawaban Fabio dan membuat fungsi yang menambahkan kunci kustom ke string URL tanpa memuat ulang halaman.

function insertUrlParam(key, value) {
    if (history.pushState) {
        let searchParams = new URLSearchParams(window.location.search);
        searchParams.set(key, value);
        let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams.toString();
        window.history.pushState({path: newurl}, '', newurl);
    }
}
Aram Hovhannisyan
sumber
0

Maka API riwayat adalah apa yang Anda cari. Jika Anda juga ingin mendukung browser lama, cari pustaka yang kembali memanipulasi tag hash URL jika browser tidak menyediakan API riwayat.

chucktator
sumber