Sayfayı yeniden yüklemeden bir sorgu dizesini değiştirme


114

Bir fotoğraf galerisi oluşturuyorum ve fotoğraflara göz atıldığında sorgu dizesini ve başlığını değiştirebilmek istiyorum.

Aradığım davranış genellikle sürekli / sonsuz sayfanın bazı uygulamalarında görülür, burada siz aşağı kaydırırken sorgu dizesi sayfa numarasını ( http://x.com?page=4 ) vb. Artırmaya devam eder . Bu, teoride basit, ancak büyük tarayıcılarda güvenli olan bir şey istiyorum.

Bu harika gönderiyi buldum ve örneği takip etmeye çalışıyordum window.history.pushstate, ancak bu benim için işe yaramıyor gibi görünüyor. İdeal olup olmadığından emin değilim çünkü tarayıcı geçmişini değiştirmeyi gerçekten umursamıyorum.

Sadece o anda görüntülenen fotoğrafa, fotoğraf her değiştirildiğinde sayfayı yeniden yüklemeden yer imi koyma olanağı sunabilmek istiyorum.

Sorgu dizesini değiştiren bir sonsuz sayfa örneği: http://tumbledry.org/

UPDATE bu yöntemi buldu:

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

benim için çalışıyor gibi görünüyor, ancak yeni bir Chrome kullanıyorum .. muhtemelen eski tarayıcılarda bazı sorunlara neden olur?


Sorgu dizesini dinamik olarak güncelleyen örnek bir siteye bir bağlantı gönderebilir misiniz? Ben bu yapılabilir sanmıyorum ama olabilir karma değerini değiştirmek ve o istediğini elde etmek yeterli olabilir.
Sivri



olası yinelenen yeni web Dropbox sayfa yenileme olmadan URL'yi değiştirebilir Neden? ve bir kopyası olarak işaretlenen üç soru
Quentin

@Quentin. Yalnızca bir yakın oy hakkınız olabilir ...:)
gdoron Monica'yı destekliyor

Yanıtlar:


185

Hash modifikasyonu arıyorsanız, çözümünüz iyi çalışıyor. Ancak sorguyu değiştirmek isterseniz, söylediğiniz gibi pushState'i kullanabilirsiniz. İşte bunu doğru bir şekilde uygulamanıza yardımcı olabilecek bir örnek. Test ettim ve iyi çalıştı:

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

Sayfayı yeniden yüklemez, ancak yalnızca URL sorgusunu değiştirmenize izin verir. Protokolü veya ana bilgisayar değerlerini değiştiremezsiniz. Ve tabii ki HTML5 Geçmiş API'sini işleyebilen modern tarayıcılar gerektiriyor.

Daha fazla bilgi için:

http://diveintohtml5.info/history.html

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


6
Sana kısaltmak inanıyorum window.location.protocol + '//' + window.location.hostlazım: window.location.origin.
Garrett

4
Ayrıca, ek bir bilgi parçası için, göreceli yollar da çalışır history.pushState(). Gerçek bir stateargüman da gerekmez. Bunların her ikisi de, history.pushState(null, '', '/foo?bar=true')yeni url'niz aynı ana bilgisayar / bağlantı noktasındaymış gibi basit bir şey yapabileceğiniz anlamına gelir .
Blaskovicz

23
Yeni durumun tarayıcı geçmişinde görünmesini istemiyorsanız history.replaceState(), aynı bağımsız değişkenlerle kullanabileceğinizi unutmayın.
Blackus

6
History.replaceState () KULLANIN aksi halde tarayıcınızda GERİ düğmesine iki kez tıklamanız gerekir
Zhenya

4
modern tarayıcılarda şunları yapabilirsiniz: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

Fabio'nun cevabından yola çıkarak, bu soruyla karşılaşan herkes için muhtemelen faydalı olacak iki işlev yarattım. Bu iki işlevle, insertParam()argüman olarak bir anahtar ve değerle çağrı yapabilirsiniz . Ya URL parametresini ekler ya da aynı anahtara sahip bir sorgu parametresi zaten mevcutsa, bu parametreyi yeni değerle değiştirir:

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

nasıl işlevleriniz set ve deletenew URLSearchParams() olarak yerel yöntemlerinden daha iyidir ? her iki durumda da bunu tarihe history.pushState()
koymalıyız

1
new URLSearchParams()hiçbir IE sürümü tarafından desteklenmiyor
jmona789

Teşekkür ederim @ jmona789 bu benim için mükemmel çalıştı ve tam olarak aradığım
şeydi

7

Aşağıdaki JavaScript kitaplığını büyük bir başarıyla kullandım:

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

HTML5 geçmiş API'sinin yanı sıra eski tarayıcılar için bir geri dönüş yöntemini (# kullanarak) destekler.

Bu kütüphane esasen "history.pushState" etrafında bir çoklu dolgudur.


müthiş! tüm tarayıcılarla test ettin mi ??
Sonic Soul

Uygulamam IE7 +, Firefox 3.6+, Safari 5 ve Chrome 16+ ile test edildi. Muhtemelen diğer tarayıcılarla da çalışıyor, ancak onu kullanan çeşitli sistemlerde herhangi bir şikayetim olmadı.
Ian Newson

harika. yani şu anda .. window.location.href dosyasına yazarken & yerine bir # koymak benim için çalışıyor. bununla sayfayı yeniden yüklemiyor. IE'de test ettiğimde kırılacağına eminim .. bu noktada önerdiğiniz kitaplık ile gideceğim. teşekkürler
Sonic Soul

# Yöntemi, çok geniş bir tarayıcı desteğine sahip olması açısından iyi bir yöntemdir. URL'nin # kısmı tarayıcı tarafından gönderilmediğinden, bu bilgileri sunucuya yapılan isteklere eklemeniz gerektiğinde işler karmaşıklaşabilir. Referans verdiğim kitaplığı da içeren bunun etrafından dolaşan yollar var. Ayrıca, HTML5 geçmiş API'sini kullanmak, URL'lerinizi genel olarak kısaltmaya yardımcı olur ve durumu geri yüklemek için daha az istemci tarafı çalışması gerektirir.
Ian Newson

# Yöntemi sosyal medya paylaşımı için de sorunludur; Twitter, Facebook ve muhtemelen diğerleri, önizlemeler veya paylaşıma geri bağlantılar oluştururken bağlantı etiketleriyle iyi oynamıyor.
mirth23

5

Fabio'nun yanıtını iyileştirmek ve sayfayı yeniden yüklemeden URL dizesine özel anahtar ekleyen bir işlev oluşturmak istiyorum.

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

O halde geçmiş API'si tam olarak aradığınız şeydir. Eski tarayıcıları da desteklemek istiyorsanız, tarayıcı geçmiş API'sini sağlamıyorsa URL'nin karma etiketini değiştirmeye geri dönen bir kitaplık arayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.