Modyfikowanie ciągu zapytania bez ponownego ładowania strony

114

Tworzę galerię zdjęć i chciałbym mieć możliwość zmiany ciągu zapytania i tytułu podczas przeglądania zdjęć.

Zachowanie, którego szukam, jest często widoczne w niektórych implementacjach ciągłej / nieskończonej strony, gdzie podczas przewijania ciągu zapytania w dół ciąg zapytania zwiększa numer strony ( http://x.com?page=4 ) itd. Tak powinno być w teorii proste, ale chciałbym czegoś, co jest bezpieczne we wszystkich głównych przeglądarkach.

znalazłem ten świetny post i próbowałem podążać za przykładem window.history.pushstate, ale to nie wydaje się działać dla mnie. I nie jestem pewien, czy jest idealny, ponieważ tak naprawdę nie obchodzi mnie modyfikowanie historii przeglądarki.

Chcę tylko móc zaoferować możliwość dodania zakładek do aktualnie oglądanego zdjęcia bez ponownego ładowania strony za każdym razem, gdy zdjęcie jest zmieniane.

Oto przykład nieskończonej strony, która modyfikuje ciąg zapytania: http://tumbledry.org/

UPDATE znalazło tę metodę:

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

wydaje się, że działa dla mnie, ale korzystam z nowego chrome .. prawdopodobnie spowodowałoby to problemy ze starszymi przeglądarkami?

Sonic Soul
źródło
Czy możesz opublikować łącze do przykładowej witryny, która dynamicznie aktualizuje ciąg zapytania? Nie sądzę, że można to zrobić, ale może zmienić wartość hash i że może być tyle, aby dostać to, czego chcesz.
Pointy
możliwy duplikat Dlaczego nowy internetowy Dropbox może zmienić adres URL bez odświeżania strony? a trzy pytania zaznaczono jako duplikat
Quentin,
@Quentin. Możesz mieć tylko jeden bliższy głos ...:)
gdoron wspiera Monikę

Odpowiedzi:

185

Jeśli szukasz modyfikacji skrótu, Twoje rozwiązanie działa poprawnie. Jeśli jednak chcesz zmienić zapytanie, możesz użyć pushState, jak powiedziałeś. Oto przykład, który może pomóc we właściwym wdrożeniu. Przetestowałem i działało dobrze:

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

Nie przeładowuje strony, a jedynie umożliwia zmianę zapytania URL. Nie możesz zmienić protokołu ani wartości hosta. I oczywiście, że wymaga nowoczesnych przeglądarek, które potrafią przetwarzać interfejs API historii HTML5.

Po więcej informacji:

http://diveintohtml5.info/history.html

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

Fabio Nolasco
źródło
6
Wierzę, że można skrócić window.location.protocol + '//' + window.location.hostdo zaledwie: window.location.origin.
Garrett
4
Ponadto, aby uzyskać dodatkowe informacje, ścieżki względne działają również z history.pushState(). Nie statejest też wymagany żaden argument. Oba oznaczają, że możesz zrobić coś prostego, na przykład history.pushState(null, '', '/foo?bar=true')jeśli nowy adres URL znajduje się na tym samym hoście / porcie.
Blaskovicz
23
Pamiętaj, że jeśli nie chcesz, aby nowy stan pojawiał się w historii przeglądarki, możesz użyć history.replaceState()tych samych argumentów.
Blackus
6
UŻYJ history.replaceState () w przeciwnym razie musisz dwukrotnie kliknąć przycisk WSTECZ w przeglądarce
Zhenya
4
w nowoczesnych przeglądarkach możesz po prostu zrobić: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

Opierając się na odpowiedzi Fabio, stworzyłem dwie funkcje, które prawdopodobnie będą przydatne dla każdego, kto natknie się na to pytanie. Dzięki tym dwóm funkcjom możesz wywołać insertParam()z kluczem i wartością jako argumentem. Doda parametr adresu URL lub, jeśli parametr zapytania już istnieje z tym samym kluczem, zmieni ten parametr na nową wartość:

//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
źródło
w jaki sposób twoje funkcje są lepsze niż w new URLSearchParams()przypadku natywnych metod ustawiania i usuwania ? w obu przypadkach musimy przenieść to do historiihistory.pushState()
AlexNikonov
1
new URLSearchParams()nie jest obsługiwany przez żadną wersję IE
jmona789
Dziękuję @ jmona789, to zadziałało idealnie dla mnie i było dokładnie tym, czego szukałem
mknopf
7

Z wielkim sukcesem korzystałem z następującej biblioteki JavaScript:

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

Obsługuje interfejs API historii HTML5, a także metodę awaryjną (przy użyciu #) dla starszych przeglądarek.

Ta biblioteka jest w zasadzie wypełnieniem wokół `history.pushState '.

Ian Newson
źródło
niesamowite! czy przetestowałeś to we wszystkich przeglądarkach?
Sonic Soul
Moja implementacja została przetestowana w IE7 +, Firefox 3.6+, Safari 5 i Chrome 16+. Prawdopodobnie działa również z innymi przeglądarkami, ale nie miałem żadnych skarg w kilku systemach wdrożonych przy jej użyciu.
Ian Newson
świetny. więc teraz ... po prostu wstawienie # zamiast & podczas pisania do window.location.href działa dla mnie. w tym sensie, że nie ładuje ponownie strony. Jestem pewien, że się zepsuje, gdy przetestuję go w IE ... w tym momencie pójdę z biblioteką, którą zasugerowałeś. dzięki
Sonic Soul
Metoda # jest dobra, ponieważ obsługuje bardzo szeroką przeglądarkę. Sytuacja może się skomplikować, gdy trzeba zawrzeć te informacje w żądaniach do serwera, ponieważ # część adresu URL nie jest wysyłana przez przeglądarkę. Są na to sposoby, łącznie z biblioteką, do której się odwołałem. Ponadto użycie interfejsu API historii HTML5 pomaga ogólnie skrócić adresy URL i wymaga mniej pracy po stronie klienta, aby przywrócić stan.
Ian Newson
Metoda # jest również problematyczna w przypadku udostępniania w mediach społecznościowych; Twitter, Facebook i być może inne nie współpracują dobrze z tagami kotwicy podczas tworzenia podglądów lub linków do udziału.
wesołość
5

Chcę poprawić odpowiedź Fabio i stworzyć funkcję, która dodaje klucz niestandardowy do ciągu adresu URL bez ponownego ładowania strony.

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
źródło
0

W takim razie API historii jest dokładnie tym, czego szukasz. Jeśli chcesz obsługiwać również starsze przeglądarki, poszukaj biblioteki, która powraca do manipulowania tagiem skrótu adresu URL, jeśli przeglądarka nie zapewnia interfejsu API historii.

chucktator
źródło