Jak zmodyfikować adres URL bez ponownego ładowania strony?

2376

Czy istnieje sposób na zmodyfikowanie adresu URL bieżącej strony bez ponownego ładowania strony?

Chciałbym uzyskać dostęp do części przed hashem #, jeśli to możliwe.

Muszę tylko zmienić część po domenie, więc to nie tak, że naruszam zasady dotyczące wielu domen.

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads
Błysk
źródło
139
Na przykład, aby ułatwić zrozumienie pytania, to właśnie robi Facebook, gdy otwierasz zdjęcie. Pasek adresu URL zmienia się tak, aby wskazywał BEZPOŚREDNIO na to zdjęcie, dzięki czemu możesz udostępnić adres URL bez utraty miejsca na stronie. Pamiętasz strony oparte na kadrowaniu w ostatniej dekadzie? Możesz uzyskać tylko adres strony głównej, ponieważ zmieniają się tylko ramki wewnętrzne. I to było okropne.
Spidey
Chociaż history.pushState()jest to prawdopodobnie właściwa odpowiedź tutaj, w tej sytuacji (w zależności od konkretnych okoliczności ...) możliwość skorzystania z przekierowania po stronie serwera (na przykład za pomocą dyrektywy RewriteRule Apache) jest czymś, co warto rozważyć, a przynajmniej być świadomym. Pomyślałem, że należy o tym wspomnieć!
Doin

Odpowiedzi:

2032

Można to teraz zrobić w Chrome, Safari, Firefox 4+ i Internet Explorer 10pp4 +!

Aby uzyskać więcej informacji, zobacz odpowiedź na to pytanie: Aktualizowanie paska adresu nowym adresem URL bez mieszania lub przeładowywania strony

Przykład:

 function processAjaxData(response, urlPath){
     document.getElementById("content").innerHTML = response.html;
     document.title = response.pageTitle;
     window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", urlPath);
 }

Następnie możesz użyć window.onpopstatedo wykrycia nawigacji przycisku Wstecz / Dalej :

window.onpopstate = function(e){
    if(e.state){
        document.getElementById("content").innerHTML = e.state.html;
        document.title = e.state.pageTitle;
    }
};

Bardziej szczegółowe spojrzenie na manipulowanie historią przeglądarki znajduje się w tym artykule MDN .

David Murdoch
źródło
272
Jak Facebook robi to w IE7?
Dominic
57
@CHiRiLo sprawdź history.js, który zapewnia rezerwę dla przeglądarek, które nie obsługują interfejsu API historii HTML5.
David Murdoch,
23
@infensus Jeśli gdzieś w adresie URL jest znak #, ta sztuczka istnieje od lat ..
Izkata
34
Co oznacza „pp4 +” część „IE10pp4 +”?
Scott Tesler,
34
podgląd platformy 4
David Murdoch,
585

W HTML5 wprowadzono metody history.pushState()i history.replaceState(), które pozwalają odpowiednio dodawać i modyfikować wpisy historii.

window.history.pushState('page2', 'Title', '/page2.php');

Przeczytaj więcej na ten temat stąd

Vivart
źródło
12
Może nie działać file:///ze względów bezpieczeństwa, np. Firefox 30. Test localhostz python -m SimpleHTTPServer.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
6
Pierwszym parametrem ma być obiekt, a nie tylko ciąg znaków.
Alexis Wilke
40
IMO to naprawdę najlepsza odpowiedź. Jeśli wszystko, co chcesz zrobić, to zaktualizować bieżący adres URL ({}, null, strNewPath) to wszystko, co musisz zrobić. Najlepiej przetestować najpierw z if (history.pushState) {}
Craig Jacobs
7
możesz po prostu wpisać null dla pierwszych 2 parametrów, jeśli nie chcesz ich zmieniać. Możesz również użyć bezwzględnego adresu URL dla trzeciego parametru.
Andrew
3
Byłoby miło, gdybyś umieścił więcej informacji tylko w odpowiedzi. Nie mam pojęcia, co robi parametr 1.
RedClover
129

Możesz również użyć HTML5 replaceState, jeśli chcesz zmienić adres URL, ale nie chcesz dodawać wpisu do historii przeglądarki:

if (window.history.replaceState) {
   //prevents browser from storing history with each change:
   window.history.replaceState(statedata, title, url);
}

Spowodowałoby to „uszkodzenie” funkcji przycisku wstecz. Może to być wymagane w niektórych przypadkach, na przykład w galerii obrazów (gdzie chcesz, aby przycisk Wstecz wrócił do strony indeksu galerii, zamiast przesuwać się po każdym oglądanym obrazie), jednocześnie nadając każdemu obrazowi swój unikalny adres URL.

George Filippakos
źródło
109

Oto moje rozwiązanie (newUrl to nowy adres URL, który chcesz zastąpić bieżącym):

history.pushState({}, null, newUrl);
Haimei
źródło
1
Najlepiej najpierw przetestować za pomocą if (history.pushState) {} Na wszelki wypadek stara przeglądarka.
Craig Jacobs
To już nie działa w Firefoksie: Operacja jest niepewna.
kkatusic
Dzięki temu podejściu użytkownik może nawet ustawić zakładkę, pięknie! Teraz mogę zaktualizować adres URL po wprowadzeniu danych przez użytkownika, a on może bezpośrednio utworzyć zakładkę, bez względu na ustawienia.
codepleb
106

UWAGA: Jeśli pracujesz z przeglądarką HTML5, powinieneś zignorować tę odpowiedź. Jest to teraz możliwe, jak widać w innych odpowiedziach.

Nie można zmodyfikować adresu URL w przeglądarce bez ponownego ładowania strony. Adres URL reprezentuje ostatnią załadowaną stronę. Jeśli to zmienisz ( document.location), spowoduje to ponowne załadowanie strony.

Jednym z oczywistych powodów jest to, że piszesz witrynę, www.mysite.comktóra wygląda jak strona logowania do banku. Następnie zmieniasz pasek adresu URL przeglądarki, aby powiedzieć www.mybank.com. Użytkownik będzie zupełnie nieświadomy, że tak naprawdę na niego patrzy www.mysite.com.

Robin Day
źródło
33
Nie chcę zmieniać domeny, tylko ścieżkę i nazwę pliku.
TheFlash
5
To wciąż nie powstrzymuje potencjalnych zagrożeń bezpieczeństwa, ponieważ przeglądarka nie ma pojęcia, że ​​domena / moja witryna i domena / inna witryna są uważane przez użytkownika za „bezpieczne”. Może pytanie powinno brzmieć dlaczego chcesz zmienić adres URL? Jeśli ma to ukryć przed użytkownikiem, możesz po prostu uruchomić aplikację w ramce iframe.
Robin Day
5
Możesz to zrobić za pomocą Flasha. Umożliwi to modyfikację adresu URL bez żądania. Jest to możliwe, ponieważ Flash działa poza przeglądarką, ale bardzo ściśle z nią.
Nick Berardi,
142
Muszę powiedzieć, że istnieją całkowicie uzasadnione powody, dla których warto zmodyfikować adres URL po stronie klienta paska adresu. Na przykład, jeśli masz tabelę danych ze stronicowaniem, sortowaniem i filtrowaniem i chcesz, aby te rzeczy były zasilane przez Ajax, ale nadal aktualizuj adres URL, aby bieżący stan strony był znaczący. Rozumiem zagrożenia bezpieczeństwa związane ze zmianą nazwy domeny (phishing itp.), Ale dlaczego przeglądarki nie pozwalają na modyfikację tylko części adresu URL po prawej stronie domeny najwyższego poziomu za pomocą skryptu?
Niedziela Ironfoot
41
ta odpowiedź nie jest już w 100% prawdziwa. Zobacz moją odpowiedź, aby poznać szczegóły.
David Murdoch
83
parent.location.hash = "hello";
Jaskółka oknówka.
źródło
15
Chcę zmienić adres URL, a nie tylko skrót - #mydata
TheFlash
42
Zmiana skrótu może być użyteczna w ajax, ponieważ jest to rodzaj stanu bez użycia plików cookie, można go zaksięgować i jest kompatybilny z przyciskami wstecz przeglądarki. Gmail wykorzystuje to obecnie, aby uczynić go bardziej przyjaznym dla przeglądarki.
Matthew Lock
@Jarvis: jaka jest różnica?
głośny
@noisy Śledzenie po stronie serwera nie widzi skrótów, chyba że zostanie wysłane bezpośrednio do usługi śledzenia.
RedYetiCo,
nie jest to użyteczne, jeśli używasz frameworka mvc, który trasuje w skrócie, na przykład szkieletu.
catbadger
27

W nowoczesnych przeglądarkach i HTML5 istnieje metoda wywoływana pushStatew oknie history. To zmieni adres URL i prześle go do historii bez ładowania strony.

Możesz użyć tego w ten sposób, zajmie 3 parametry, 1) stan obiektu 2) tytuł i adres URL):

window.history.pushState({page: "another"}, "another page", "example.html");

Spowoduje to zmianę adresu URL, ale nie przeładuje strony. Ponadto nie sprawdza, czy strona istnieje, więc jeśli wykonasz kod JavaScript reagujący na adres URL, możesz z nimi pracować w ten sposób.

Jest też coś, history.replaceState()co robi dokładnie to samo, tyle że zmodyfikuje bieżącą historię zamiast tworzyć nową!

Możesz także utworzyć funkcję, aby sprawdzić, czy history.pushStateistnieje, a następnie kontynuować resztę w następujący sposób:

function goTo(page, title, url) {
  if ("undefined" !== typeof history.pushState) {
    history.pushState({page: page}, title, url);
  } else {
    window.location.assign(url);
  }
}

goTo("another page", "example", 'example.html');

Możesz także zmienić #for <HTML5 browsers, który nie przeładuje strony. W ten sposób Angular wykorzystuje SPA zgodnie z hashtagiem ...

Zmiana #jest dość łatwa, wykonując:

window.location.hash = "example";

Możesz to wykryć w następujący sposób:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}
Alireza
źródło
Czy window.onhashchangei window.onpopstatezrobić to samo w tym przypadku?
J0ANMM,
Jak również ładować zawartość strony? To po prostu zastępuje adres URL
MD. Atiqur Rahman
Załaduj zawartość, tak jak zwykle w przypadku ajax.
AndroidDev
26

HTML5 replaceState jest odpowiedzią, jak już wspomniano w Vivart i geo1701. Jednak nie jest obsługiwany we wszystkich przeglądarkach / wersjach. History.js zawiera funkcje stanu HTML5 i zapewnia dodatkową obsługę przeglądarek HTML4.

Thomas Stjernegaard Jeppesen
źródło
24

Przed wersją HTML5 możemy użyć:

parent.location.hash = "hello";

i:

window.location.replace("http:www.example.com");

Ta metoda spowoduje ponowne załadowanie strony, ale HTML5 wprowadził tę, history.pushState(page, caption, replace_url)która nie powinna ponownie ładować strony.

Połysk
źródło
2
Problem history.pushState(..)polega na tym, że jeśli chcesz przekierować do innej domeny, obowiązują zasady dotyczące wielu domen. Podczas window.location.replace(..)przekierowania do innej domeny jest możliwe.
OSWorX
23

Jeśli próbujesz zezwolić użytkownikom na dodawanie zakładek do zakładek / udostępnianie stron, a nie potrzebujesz dokładnie tego adresu URL i nie używasz kotwic mieszających do niczego innego, możesz to zrobić na dwa sposoby Części; korzystasz z location.hash omówionego powyżej, a następnie zaimplementujesz sprawdzanie na stronie głównej, aby wyszukać adres URL z zakotwiczeniem skrótu i ​​przekierować do następnego wyniku.

Na przykład:

1) Użytkownik jest włączony www.site.com/section/page/4

2) Użytkownik wykonuje pewne czynności, które zmieniają adres URL na www.site.com/#/section/page/6(z skrótem). Załóżmy, że załadowałeś na stronę prawidłową treść strony 6, więc oprócz skrótu użytkownik nie jest zbytnio zakłócany.

3) Użytkownik przekazuje ten adres URL komuś innemu lub dodaje go do zakładek

4) Ktoś inny lub ten sam użytkownik w późniejszym terminie udaje się do www.site.com/#/section/page/6

5) Kod na www.site.com/przekierowuje użytkownika www.site.com/section/page/6, używając czegoś takiego:

if (window.location.hash.length > 0){ 
   window.location = window.location.hash.substring(1);
}

Mam nadzieję, że to ma sens! Jest to przydatne podejście w niektórych sytuacjach.

Jeremy Warne
źródło
17

Poniżej znajduje się funkcja zmiany adresu URL bez ponownego ładowania strony. Jest obsługiwany tylko dla HTML5.

  function ChangeUrl(page, url) {
        if (typeof (history.pushState) != "undefined") {
            var obj = {Page: page, Url: url};
            history.pushState(obj, obj.Page, obj.Url);
        } else {
            window.location.href = "homePage";
            // alert("Browser does not support HTML5.");
        }
    }

  ChangeUrl('Page1', 'homePage');
Suraj
źródło
2
@Zielona strona to krótki tytuł stanu, do którego się przeprowadzasz. Firefox obecnie ignoruje ten parametr, chociaż może go używać w przyszłości. Przekazanie tutaj pustego ciągu powinno być bezpieczne przed przyszłymi zmianami metody. Od: developer.mozilla.org/en-US/docs/Web/API/…
Snook
13

Wszelkie zmiany lokalizacji (albo window.locationalbo document.location) spowodują żądanie dotyczące tego nowego adresu URL, jeśli nie zmienisz tylko fragmentu adresu URL. Jeśli zmienisz adres URL, zmienisz adres URL.

Użyj technik przepisywania adresów URL po stronie serwera, takich jak mod_rewrite Apache, jeśli nie podoba ci się adres URL, którego aktualnie używasz.

Gumbo
źródło
Czy mogę użyć „location.pathname”?
TheFlash
3
Nie, zmiana tego atrybutu spowoduje również żądanie.
Gumbo
11

Możesz dodać tagi kotwicy. Używam tego w mojej witrynie, aby móc śledzić za pomocą Google Analytics, co ludzie odwiedzają na stronie.

Po prostu dodaję tag zakotwiczenia, a następnie część strony, którą chcę śledzić:

var trackCode = "/#" + urlencode($("myDiv").text());
window.location.href = "http://www.piano-chords.net" + trackCode;
pageTracker._trackPageview(trackCode);
Nate
źródło
9

Jak zauważył Thomas Stjernegaard Jeppesen, możesz użyć History.js do modyfikowania parametrów URL, podczas gdy użytkownik porusza się po twoich linkach i aplikacjach Ajax.

Od tej odpowiedzi minął prawie rok, a History.js urósł i stał się bardziej stabilny i działał w różnych przeglądarkach. Teraz można go używać do zarządzania stanami historii w zgodnych z HTML5, a także w wielu przeglądarkach obsługujących tylko HTML4. W tym demo możesz zobaczyć przykład, jak to działa (a także móc wypróbować jego funkcje i ograniczenia.

Jeśli potrzebujesz pomocy w korzystaniu i implementowaniu tej biblioteki, radzę spojrzeć na kod źródłowy strony demonstracyjnej: zobaczysz, że jest to bardzo łatwe.

Wreszcie, aby uzyskać wyczerpujące wyjaśnienie problemów związanych z używaniem skrótów (i skrótów), sprawdź ten link Benjamina Luptona.

Erenor Paz
źródło
7

Możesz użyć tej pięknej i prostej funkcji, aby to zrobić w dowolnym miejscu swojej aplikacji.

function changeurl(url, title) {
    var new_url = '/' + url;
    window.history.pushState('data', 'Title', new_url);
    document.title = title;
}

Możesz nie tylko edytować adres URL, ale także aktualizować tytuł wraz z nim.

Całkiem pomocny wszystkim.

Dheeraj Thedijje
źródło
1
Działa jak urok nawet dla kotwicwindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD