Ändern einer Abfragezeichenfolge ohne erneutes Laden der Seite

114

Ich erstelle eine Fotogalerie und möchte die Abfragezeichenfolge und den Titel ändern können, wenn die Fotos durchsucht werden.

Das Verhalten, nach dem ich suche, tritt häufig bei einigen Implementierungen von fortlaufenden / unendlichen Seiten auf, bei denen die Abfragezeichenfolge beim Scrollen nach unten die Seitenzahl ( http://x.com?page=4 ) usw. erhöht . Dies sollte der Fall sein Theoretisch einfach, aber ich möchte etwas, das in allen gängigen Browsern sicher ist.

Ich habe diesen großartigen Beitrag gefunden und versucht, dem Beispiel zu folgen window.history.pushstate, aber das scheint für mich nicht zu funktionieren. Und ich bin mir nicht sicher, ob es ideal ist, weil es mir nicht wirklich wichtig ist, den Browserverlauf zu ändern.

Ich möchte nur die Möglichkeit bieten, das aktuell angezeigte Foto mit einem Lesezeichen zu versehen, ohne die Seite jedes Mal neu zu laden, wenn das Foto geändert wird.

Hier ist ein Beispiel für eine unendliche Seite, die die Abfragezeichenfolge ändert: http://tumbledry.org/

UPDATE hat diese Methode gefunden:

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

es scheint für mich zu funktionieren, aber ich bin auf einem neuen Chrom .. es würde wahrscheinlich einige Probleme mit älteren Browsern verursachen?

Sonic Soul
quelle
Können Sie einen Link zu einer Beispielsite veröffentlichen, deren Abfragezeichenfolge dynamisch aktualisiert wird? Ich denke nicht, dass dies möglich ist, aber Sie können den Hash-Wert ändern, und das könnte ausreichen, um das zu bekommen, was Sie wollen.
Pointy
Mögliches Duplikat von Warum kann die neue Web-Dropbox die URL ohne Seitenaktualisierung ändern? und die drei Fragen, die es als Duplikat von
Quentin
@QUentin. Sie können nur eine nähere Abstimmung haben ...:)
Gdoron unterstützt Monica

Antworten:

185

Wenn Sie nach einer Hash-Änderung suchen, funktioniert Ihre Lösung einwandfrei. Wenn Sie jedoch die Abfrage ändern möchten, können Sie wie gesagt den pushState verwenden. Hier ist ein Beispiel, das Ihnen bei der ordnungsgemäßen Implementierung helfen kann. Ich habe getestet und es hat gut funktioniert:

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

Die Seite wird nicht neu geladen, sondern Sie können nur die URL-Abfrage ändern. Sie können das Protokoll oder die Hostwerte nicht ändern. Und natürlich erfordert es moderne Browser, die die HTML5-Verlaufs-API verarbeiten können.

Für mehr Informationen:

http://diveintohtml5.info/history.html

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

Fabio Nolasco
quelle
6
Ich glaube, Sie können window.location.protocol + '//' + window.location.hostauf nur verkürzen : window.location.origin.
Garrett
4
Für zusätzliche Informationen funktionieren auch relative Pfade history.pushState(). Es stateist auch kein tatsächliches Argument erforderlich. Beides bedeutet, dass Sie etwas Einfaches tun können, history.pushState(null, '', '/foo?bar=true')wenn sich Ihre neue URL auf demselben Host / Port befindet.
Blaskovicz
23
Beachten Sie, dass Sie history.replaceState()mit denselben Argumenten arbeiten können, wenn der neue Status nicht im Browserverlauf angezeigt werden soll .
Blackus
6
USE history.replaceState () andernfalls müssen Sie zweimal in Ihrem Browser auf die Schaltfläche BACK klicken
Zhenya
4
In modernen Browsern können Sie einfach Folgendes tun: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

Aufbauend auf Fabios Antwort habe ich zwei Funktionen erstellt, die wahrscheinlich für jeden nützlich sein werden, der über diese Frage stolpert. Mit diesen beiden Funktionen können Sie insertParam()mit einem Schlüssel und einem Wert als Argument aufrufen . Entweder wird der URL-Parameter hinzugefügt, oder wenn bereits ein Abfrageparameter mit demselben Schlüssel vorhanden ist, wird dieser Parameter in den neuen Wert geändert:

//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
quelle
Wie sind Ihre Funktionen besser als new URLSearchParams()mit den nativen Methoden zum Festlegen und Löschen ? In beiden Fällen müssen wir es mithistory.pushState()
AlexNikonov
1
new URLSearchParams()wird von keiner Version von IE
jmona789
Danke @ jmona789 das hat perfekt für mich funktioniert und war genau das, wonach ich gesucht habe
mknopf
7

Ich habe die folgende JavaScript-Bibliothek mit großem Erfolg verwendet:

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

Es unterstützt die HTML5-Verlaufs-API sowie eine Fallback-Methode (mit #) für ältere Browser.

Diese Bibliothek ist im Wesentlichen eine Polyfüllung um `history.pushState '.

Ian Newson
quelle
genial! Hast du es mit allen Browsern getestet?
Sonic Soul
Meine Implementierung wurde in IE7 +, Firefox 3.6+, Safari 5 und Chrome 16+ getestet. Es funktioniert wahrscheinlich auch mit anderen Browsern, aber ich hatte keine Beschwerden in den verschiedenen Systemen, die damit bereitgestellt wurden.
Ian Newson
großartig. Also jetzt ... einfach ein # anstelle eines & setzen, wenn ich in window.location.href schreibe, funktioniert für mich. , dass die Seite nicht neu geladen wird. Ich bin sicher, es wird kaputt gehen, wenn ich es in IE teste. An diesem Punkt werde ich mit der Bibliothek gehen, die Sie vorgeschlagen haben. danke
Sonic Soul
Die # -Methode ist insofern gut, als sie eine sehr breite Browserunterstützung bietet. Es kann kompliziert werden, wenn Sie diese Informationen in Anforderungen an den Server aufnehmen müssen, da der # Teil der URL nicht vom Browser gesendet wird. Es gibt Möglichkeiten, dies zu umgehen, einschließlich der Bibliothek, auf die ich verwiesen habe. Darüber hinaus hilft die Verwendung der HTML5-Verlaufs-API dabei, Ihre URLs insgesamt zu verkürzen, und erfordert weniger clientseitige Arbeit, um den Status wiederherzustellen.
Ian Newson
Die # -Methode ist auch für das Teilen von sozialen Medien problematisch. Twitter, Facebook und möglicherweise andere spielen beim Erstellen von Vorschauen oder Links zurück zur Freigabe nicht gut mit Ankertags.
mirth23
5

Ich möchte Fabios Antwort verbessern und eine Funktion erstellen, die der URL-Zeichenfolge einen benutzerdefinierten Schlüssel hinzufügt, ohne die Seite neu zu laden.

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
quelle
0

Dann ist die Verlaufs-API genau das, wonach Sie suchen. Wenn Sie auch ältere Browser unterstützen möchten, suchen Sie nach einer Bibliothek, die auf die Bearbeitung des Hash-Tags der URL zurückgreift, wenn der Browser die Verlaufs-API nicht bereitstellt.

Chucktator
quelle