Ändern Sie die URL im Browser, ohne die neue Seite mit JavaScript zu laden

297

Wie hätte ich eine JavaScript- Aktion, die einige Auswirkungen auf die aktuelle Seite haben könnte, aber auch die URL im Browser ändern würde. Wenn der Benutzer auf "Neu laden" oder "Lesezeichen" klickt, wird die neue URL verwendet.

Es wäre auch schön, wenn der Zurück-Button die ursprüngliche URL neu laden würde.

Ich versuche, den JavaScript-Status in der URL aufzuzeichnen.

Steven Noble
quelle
1
Das wäre so schön. Natürlich wäre es auf Modifikationen derselben Domäne beschränkt. Eine clientseitige Steuerung des Pfads (und nicht nur des Hash) ist jedoch ein logischer Schritt, da das erneute Laden von Seiten für viele Apps eine Art "letzter Ausweg" darstellt.
Harpo
1
Eine "Art" gute Verwendung von pushState:for(i=1;i<50;i++){var txt="..................................................";txt=txt.slice(0,i)+"HTML5"+txt.slice(i,txt.length);history.pushState({}, "html5", txt);}
Derek 7 會 功夫
Beispiel für diesen Effekt in Aktion: dujour.com
Ben
2
Beispiel für diesen Effekt: facebook.com (Beim Öffnen von Bildern in der Lightbox)
Das ist eine gute Frage. Es ist jedoch eine traurige Situation, wenn diese Frage heute auf diese Weise gestellt worden wäre, wäre sie von der "Dies ist nicht die Art von Website, auf der die Leute Ihren gesamten Code für Sie schreiben" herabgestuft und aufgesprungen.
Tau

Antworten:

118

Verwenden Sie in HTML 5 die history.pushStateFunktion . Als Beispiel:

<script type="text/javascript">
var stateObj = { foo: "bar" };
function change_my_url()
{
   history.pushState(stateObj, "page 2", "bar.html");
}
var link = document.getElementById('click');
link.addEventListener('click', change_my_url, false);
</script>

und ein href:

<a href="#" id='click'>Click to change url to bar.html</a>

Wenn Sie die URL ändern möchten, ohne einen Eintrag zur Liste der Zurück-Schaltflächen hinzuzufügen, verwenden Sie history.replaceStatestattdessen.

clu3
quelle
Du hast recht, als ich das letzte Mal mit Chrome experimentiert habe. Ich habe es gerade mit Firefox 3.6 auf meinem Ubuntu versucht, es hat nicht funktioniert. Ich denke, wir müssen warten, bis HTML5 in FF
Clu3
15
Der Beispielcode wird aus developer.mozilla.org/en/DOM/Manipulating_the_browser_history ausgeschnitten und eingefügt . Was eigentlich stört zu erklären, was foo und bar in diesem Fall bedeuten.
Mikemaccana
2
Das foo und der Balken haben keine Bedeutung, es ist ein willkürlich definiertes Statusobjekt, das Sie später zurückerhalten können.
Paul Dixon
3
@ Paul: Ja, der obige Artikel enthält diese Informationen.
Mikemaccana
2
Ab dem Posten dieses Kommentars funktioniert es auf Firefox Chrome und Safari. Kein Glück mit mobiler Safari auf dem iPad oder iPhone :(
Sid
187

Wenn Sie es an der Arbeit in Browsern wollen , das nicht unterstützen , history.pushStateund history.popStatedoch ist der „alte“ Weg , um die Fragmentbezeichner zu setzen, die nicht eine Seite neu geladen verursachen.

Die Grundidee besteht darin, die window.location.hashEigenschaft auf einen Wert zu setzen, der alle benötigten Statusinformationen enthält, und dann entweder das Ereignis window.onhashchange zu verwenden oder für ältere Browser, die dies nicht unterstützen onhashchange(IE <8, Firefox <3.6), regelmäßig zu überprüfen Überprüfen Sie, ob sich der Hash geändert hat ( setIntervalz. B. mithilfe von), und aktualisieren Sie die Seite. Sie müssen auch den Hash-Wert beim Laden der Seite überprüfen, um den ursprünglichen Inhalt einzurichten.

Wenn Sie jQuery verwenden, gibt es ein Hashchange-Plugin , das die vom Browser unterstützte Methode verwendet. Ich bin mir sicher, dass es auch Plugins für andere Bibliotheken gibt.

Eine Sache, auf die Sie achten sollten, ist die Kollision mit IDs auf der Seite, da der Browser zu jedem Element mit einer passenden ID blättert.

Matthew Crumley
quelle
2
Ignorieren Suchmaschinen diese internen Links (Hashes) nicht? In meinem Szenario möchte ich, dass Spinnen auch diese Links aufgreifen.
Drew Noakes
3
@Brew, soweit ich weiß, gibt es für Suchmaschinen keine Möglichkeit, einen Teil einer Seite als separates Ergebnis zu behandeln.
Matthew Crumley
8
Es gibt jetzt einen Vorschlag, Suchmaschinen Hashes anzeigen
LKM
5
Anstatt zu verwenden setInterval, um das zu inspizieren, document.location.hashkann man das hashchangeEreignis verwenden, da es viel mehr angenommen wird. Überprüfen Sie hier, welche Browser die einzelnen Standards unterstützen . Mein aktueller Ansatz ist die Verwendung von Push / PopState in Browsern, die dies unterstützen. Bei den anderen setze ich den Hash und schaue nur den hashchangein unterstützenden Browsern. Dadurch bleibt IE <= 7 ohne Verlaufsunterstützung, jedoch mit nützlichem Permalink. Aber wen interessiert die IE <= 7-Geschichte?
Irae Carvalho
2
@gabeDel Ja, obwohl ich nicht glaube, dass Analytics den Hash aufzeichnet, hätte er dieselbe URL. Ein besserer Weg wäre, manuell _trackPageviewmit der "echten" URL der neuen Seite aufzurufen .
Matthew Crumley
37

window.location.href enthält die aktuelle URL. Sie können daraus lesen, anhängen und ersetzen, was zu einem erneuten Laden der Seite führen kann.

Wenn Sie, wie es sich anhört, den Javascript-Status in der URL aufzeichnen möchten, damit er mit einem Lesezeichen versehen werden kann, ohne die Seite neu zu laden, hängen Sie ihn nach einem # an die aktuelle URL an und lassen Sie ein durch das Onload-Ereignis ausgelöstes Javascript den aktuellen analysieren URL, um zu sehen, ob sie den gespeicherten Status enthält.

Wenn Sie eine verwenden? Anstelle eines # erzwingen Sie ein erneutes Laden der Seite. Da Sie jedoch den gespeicherten Status beim Laden analysieren, ist dies möglicherweise kein Problem. Dadurch funktionieren auch die Vorwärts- und Zurück-Tasten ordnungsgemäß.

Mondschatten
quelle
2
Das Aufzeichnen des Javascript-Status in der URL ist genau das, was ich versuche
Steven Noble
21

Ich würde stark vermuten, dass dies nicht möglich ist, da es ein unglaubliches Sicherheitsproblem wäre, wenn es so wäre. Zum Beispiel könnte ich eine Seite erstellen, die wie eine Bank-Anmeldeseite aussieht, und die URL in der Adressleiste genauso aussehen lassen wie die echte Bank !

Wenn Sie erklären, warum Sie dies tun möchten, können die Leute möglicherweise alternative Ansätze vorschlagen ...

[Bearbeiten im Jahr 2011: Seit ich diese Antwort im Jahr 2008 geschrieben habe, sind weitere Informationen zu einer HTML5-Technik bekannt geworden , mit der die URL geändert werden kann, solange sie denselben Ursprung hat.]

Paul Dixon
quelle
6
Kein so großes Problem, wenn Änderungen, die nicht neu geladen wurden, auf den Pfad, die Abfragezeichenfolge und das Fragment beschränkt waren - dh nicht auf die Berechtigung (Domäne und dergleichen).
Ollie Saunders
2
youtube.com/user/SilkyDKwan#p/u/2/gTfqaGYVfMg ist ein Beispiel, dass es möglich ist, versuchen Sie, Videos zu wechseln :)
Spidfire
Sie können nur die location.hash (alles nach dem #) ändern, wie Matthew Chumley in der akzeptierten Antwort feststellt.
Paul Dixon
2
Nutzt du Facebook? Facebook ändert die URL ohne erneutes Laden mit history.pushState().
Derek 7 會 功夫
Paul Dixon, Sie sollten den Facebook-Posteingang bemerken. Wenn Sie auf die Namen auf der linken Seite klicken, wird nur die URL geändert und der neue Chat wird in die Chatbox geladen. Die Seite wird nicht aktualisiert. Es gibt auch viel mehr
Websites
8

Die Browsersicherheitseinstellungen verhindern, dass Personen die angezeigte URL direkt ändern. Sie können sich die Phishing-Schwachstellen vorstellen, die dazu führen würden.

Die einzige Möglichkeit, die URL zu ändern, ohne die Seiten zu ändern, besteht darin, einen internen Link oder Hash zu verwenden. Beispiel: http://site.com/page.html wird zu http://site.com/page.html#item1 . Diese Technik wird häufig bei Hijax angewendet (AJAX + Geschichte bewahren).

Dabei verwende ich häufig nur Links für die Aktionen mit dem Hash als href und füge dann Klickereignisse mit jquery hinzu, die den angeforderten Hash verwenden, um die Aktion zu bestimmen und zu delegieren.

Ich hoffe, das bringt Sie auf den richtigen Weg.

Jethro Larson
quelle
Entschuldigung, aber Ihre Antwort ist nicht wahr. Ja, Sie können die URL ändern.
Derek 7 會 功夫
1
Ja, Sie können die HTML5-Verlaufs-API verwenden, sie ist jedoch nicht browserübergreifend, obwohl Sie eine Poly-Füllung verwenden können, die auf Hash-URLs zurückgreift.
Jethro Larson
8

jQuery hat ein großartiges Plugin zum Ändern der URL des Browsers, jQuery-pusher .

JavaScript pushStateund jQuery können zusammen verwendet werden, wie:

history.pushState(null, null, $(this).attr('href'));

Beispiel:

$('a').click(function (event) {

  // Prevent default click action
  event.preventDefault();     

  // Detect if pushState is available
  if(history.pushState) {
    history.pushState(null, null, $(this).attr('href'));
  }
  return false;
});


Verwenden Sie nur JavaScript history.pushState() , das den Referrer ändert, der im HTTP-Header für XMLHttpRequest-Objekte verwendet wird, die nach dem Ändern des Status erstellt wurden.

Beispiel:

window.history.pushState("object", "Your New Title", "/new-url");

Die pushState () -Methode:

pushState()Es werden drei Parameter verwendet: ein Statusobjekt, ein Titel (der derzeit ignoriert wird) und (optional) eine URL. Lassen Sie uns jeden dieser drei Parameter genauer untersuchen:

  1. Statusobjekt - Das Statusobjekt ist ein JavaScript-Objekt, das dem neuen Verlaufseintrag zugeordnet ist, der von erstellt wurde pushState(). Immer wenn der Benutzer zum neuen Status navigiert, wird ein Popstate-Ereignis ausgelöst, und die Statuseigenschaft des Ereignisses enthält eine Kopie des Statusobjekts des Verlaufseintrags.

    Das Statusobjekt kann alles sein, was serialisiert werden kann. Da Firefox Statusobjekte auf der Festplatte des Benutzers speichert, damit sie nach dem Neustart des Browsers wiederhergestellt werden können, wird der serialisierten Darstellung eines Statusobjekts eine Größenbeschränkung von 640.000 Zeichen auferlegt. Wenn Sie ein Statusobjekt übergeben, dessen serialisierte Darstellung größer als dieses ist pushState(), löst die Methode eine Ausnahme aus. Wenn Sie mehr Speicherplatz benötigen, sollten Sie sessionStorage und / oder localStorage verwenden.

  2. title - Firefox ignoriert diesen Parameter derzeit, obwohl er möglicherweise in Zukunft verwendet wird. Das Übergeben der leeren Zeichenfolge sollte vor zukünftigen Änderungen an der Methode sicher sein. Alternativ können Sie einen kurzen Titel für den Status übergeben, in den Sie wechseln.

  3. URL - Die URL des neuen Verlaufseintrags wird durch diesen Parameter angegeben. Beachten Sie, dass der Browser nicht versucht, diese URL nach einem Aufruf von pushState()zu laden, sondern möglicherweise versucht, die URL später zu laden, z. B. nachdem der Benutzer seinen Browser neu gestartet hat. Die neue URL muss nicht absolut sein. Wenn es relativ ist, wird es relativ zur aktuellen URL aufgelöst. Die neue URL muss denselben Ursprung haben wie die aktuelle URL. Andernfalls pushState()wird eine Ausnahme ausgelöst. Dieser Parameter ist optional. Wenn es nicht angegeben ist, wird es auf die aktuelle URL des Dokuments festgelegt.

Ilia Rostovtsev
quelle
3

Die Fotogalerie von Facebook verwendet dazu ein #hash in der URL. Hier sind einige Beispiel-URLs:

Bevor Sie auf "Weiter" klicken:

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507

Nach dem Klicken auf "Weiter":

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507#!/photo.php?fbid=496435457507&set=a.218088072507.133423.681812507&pid=5887085&id=681812507

Beachten Sie den Hash-Bang (#!) Unmittelbar gefolgt von der neuen URL.

Jonathon Hill
quelle
2

Was für mich history.replaceState()funktioniert , ist - Funktion, die wie folgt ist -

history.replaceState(data,"Title of page"[,'url-of-the-page']);

Dadurch wird die Seite nicht neu geladen. Sie können sie mit Javascript verwenden

Veshraj Joshi
quelle
1

Ich habe mich gefragt, ob dies möglich ist, solange der übergeordnete Pfad auf der Seite identisch ist. Es wird nur etwas Neues angehängt.

Nehmen wir also an, der Benutzer befindet sich auf der Seite: http://domain.com/site/page.html Dann kann der Browser dies zulassen location.append = new.html und die Seite wird: http://domain.com/site/page.htmlnew.htmlund der Browser ändert sie nicht.

Oder erlauben Sie der Person einfach, den Parameter get zu ändern location.get = me=1&page=1.

So wird die Originalseite http://domain.com/site/page.html?me=1&page=1und sie wird nicht aktualisiert.

Das Problem mit # ist, dass die Daten nicht zwischengespeichert werden (zumindest glaube ich nicht), wenn der Hash geändert wird. Es ist also so, als ob jedes Mal, wenn eine neue Seite geladen wird, Schaltflächen zum Zurück- und Weiterleiten auf einer Nicht- Ajax- Seite Daten zwischenspeichern können und keine Zeit für das erneute Laden der Daten aufwenden.

Nach allem, was ich gesehen habe, lädt die Yahoo-Verlaufssache bereits alle Daten auf einmal. Es scheint keine Ajax-Anfragen zu machen. Wenn also a divverwendet wird, um unterschiedliche Methodenüberstunden zu verarbeiten, werden diese Daten nicht für jeden Verlaufsstatus gespeichert.

user58670
quelle
1

Mein Code ist:

//change address bar
function setLocation(curLoc){
    try {
        history.pushState(null, null, curLoc);
        return false;
    } catch(e) {}
        location.hash = '#' + curLoc;
}

und Aktion:

setLocation('http://example.com/your-url-here');

und Beispiel

$(document).ready(function(){
    $('nav li a').on('click', function(){
        if($(this).hasClass('active')) {

        } else {
            setLocation($(this).attr('href'));
        }
            return false;
    });
});

Das ist alles :)

Tusko Trush
quelle
1

Eine einfachere Antwort, die ich präsentiere,

window.history.pushState(null, null, "/abc")

Dies wird /abcnach dem Domainnamen in der Browser-URL hinzugefügt . Kopieren Sie einfach diesen Code und fügen Sie ihn in die Browserkonsole ein. Die URL ändert sich in " https://stackoverflow.com/abc ".

Sam
quelle
0

Ich hatte Erfolg mit:

location.hash="myValue";

Es wird nur #myValuezur aktuellen URL hinzugefügt. Wenn Sie ein Ereignis auf Seite Laden auslösen müssen, können Sie damit location.hashden relevanten Wert überprüfen. Denken Sie daran, #den Wert aus dem von location.hashz

var articleId = window.location.hash.replace("#","");
Adam Hey
quelle