Modifica di una stringa di query senza ricaricare la pagina


114

Sto creando una galleria fotografica e vorrei poter cambiare la stringa di query e il titolo quando si sfogliano le foto.

Il comportamento che cerco è spesso visto con alcune implementazioni di pagina continua / infinita, dove mentre scorri verso il basso la stringa di query continua ad aumentare il numero di pagina ( http://x.com?page=4 ) ecc .. Questo dovrebbe essere semplice in teoria, ma vorrei qualcosa che sia sicuro per i principali browser.

Ho trovato questo ottimo post e stavo cercando di seguire l'esempio con window.history.pushstate, ma non sembra funzionare per me. E non sono sicuro che sia l'ideale perché non mi interessa davvero modificare la cronologia del browser.

Voglio solo essere in grado di offrire la possibilità di aggiungere ai segnalibri la foto attualmente visualizzata, senza ricaricare la pagina ogni volta che la foto viene modificata.

Ecco un esempio di pagina infinita che modifica la stringa di query: http://tumbledry.org/

UPDATE ha trovato questo metodo:

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

sembra funzionare per me, ma sono su un nuovo chrome .. probabilmente causerebbe alcuni problemi con i browser meno recenti?


Puoi pubblicare un collegamento a qualche sito di esempio che aggiorna la sua stringa di query in modo dinamico? Non penso che possa essere fatto, ma puoi cambiare il valore hash e questo potrebbe essere sufficiente per ottenere ciò che desideri.
Pointy



possibile duplicato di Perché il nuovo Dropbox web può modificare l'URL senza aggiornare la pagina? e le tre domande sono contrassegnate come un duplicato di
Quentin

@Quentin. Puoi avere solo un voto più ravvicinato ...:)
gdoron sostiene Monica il

Risposte:


185

Se stai cercando la modifica dell'hash, la tua soluzione funziona bene. Tuttavia, se desideri modificare la query, puoi utilizzare pushState, come hai detto. Ecco un esempio che potrebbe aiutarti a implementarlo correttamente. Ho provato e ha funzionato bene:

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

Non ricarica la pagina, ma consente solo di modificare la query dell'URL. Non sarai in grado di modificare il protocollo oi valori dell'host. E, naturalmente, richiede browser moderni in grado di elaborare l'API cronologia HTML5.

Per maggiori informazioni:

http://diveintohtml5.info/history.html

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


6
Io credo che si possa ridurre window.location.protocol + '//' + window.location.hostad appena: window.location.origin.
Garrett

4
Inoltre, per un'ulteriore informazione, funzionano anche i percorsi relativi history.pushState(). Non stateè nemmeno richiesto alcun argomento effettivo . Entrambi questi significano che puoi fare qualcosa di semplice come history.pushState(null, '', '/foo?bar=true')se il tuo nuovo URL si trovi sullo stesso host / porta.
Blaskovicz

23
Nota che, se non vuoi che il nuovo stato appaia nella cronologia del browser, puoi usarlo history.replaceState()con gli stessi argomenti.
Blackus

6
USA history.replaceState () altrimenti devi fare clic due volte sul pulsante INDIETRO nel tuo browser
Zhenya

4
nei browser moderni puoi semplicemente fare: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

Partendo dalla risposta di Fabio, ho creato due funzioni che probabilmente saranno utili per chi si imbatte in questa domanda. Con queste due funzioni, puoi chiamare insertParam()con una chiave e un valore come argomento. Aggiungerà il parametro URL o, se esiste già un parametro di query con la stessa chiave, cambierà quel parametro con il nuovo valore:

//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);
    }
}

in che modo le tue funzioni sono migliori rispetto new URLSearchParams()ai metodi nativi impostati ed eliminati ? in entrambi i casi dobbiamo metterlo alla storia conhistory.pushState()
AlexNikonov

1
new URLSearchParams()non è supportato da nessuna versione di IE
jmona789

Grazie @ jmona789 questo ha funzionato perfettamente per me ed era esattamente quello che stavo cercando
mknopf

7

Ho utilizzato la seguente libreria JavaScript con grande successo:

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

Supporta l'API della cronologia HTML5 e un metodo di fallback (utilizzando #) per i browser meno recenti.

Questa libreria è essenzialmente un polyfill attorno a `history.pushState '.


eccezionale! l'hai testato con tutti i browser ??
Sonic Soul

La mia implementazione è stata testata in IE7 +, Firefox 3.6+, Safari 5 e Chrome 16+. Probabilmente funziona anche con altri browser, ma non ho avuto alcun reclamo nei diversi sistemi implementati che lo utilizzano.
Ian Newson

grande. quindi in questo momento .. semplicemente mettere un # invece di un & quando si scrive a window.location.href funziona per me. in quanto non ricarica la pagina. sono sicuro che si romperà una volta che lo testerò in IE .. a quel punto andrò con la libreria che hai suggerito. grazie
Sonic Soul

Il metodo # è buono in quanto ha un supporto browser molto ampio. Le cose possono complicarsi quando è necessario includere tali informazioni nelle richieste al server, poiché la parte # dell'URL non viene inviata dal browser. Ci sono modi per aggirare questo, che include la libreria a cui ho fatto riferimento. Inoltre, l'utilizzo dell'API cronologia HTML5 aiuta a rendere i tuoi URL complessivamente più brevi e richiede meno lavoro lato client per ripristinare lo stato.
Ian Newson

Il metodo # è problematico anche per la condivisione sui social media; Twitter, Facebook e forse altri non funzionano bene con i tag di ancoraggio durante la creazione di anteprime o collegamenti alla condivisione.
allegria23

5

Voglio migliorare la risposta di Fabio e creare una funzione che aggiunge una chiave personalizzata alla stringa dell'URL senza ricaricare la pagina.

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

0

Quindi l'API della cronologia è esattamente quello che stai cercando. Se desideri supportare anche i browser legacy, cerca una libreria che ricada sulla manipolazione dell'hash tag dell'URL se il browser non fornisce l'API della cronologia.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.