Bir kullanıcının geri düğmesini kullanarak bir sayfaya ulaşıp ulaşmadığını nasıl anlarım?


90

Bu soru, kullanıcı tarayıcıda geri düğmesine bastığında izle'ye benzer , ancak aynı değil ... Bir çözümüm var ve referans ve geri bildirim için buraya gönderiyorum. Birinin daha iyi seçeneği varsa, kulaklarım!

Durum şu ki, "yerinde düzenleme", la flickr içeren bir sayfam var. Yani bir "açıklama eklemek için buraya tıklayın" DIV, tıklandığında Kaydet ve İptal düğmeleriyle bir TEXTAREA'ya dönüşür. Kaydet'e tıklamak, veritabanını güncellemek için verileri sunucuya gönderir ve yeni açıklamayı DIV'ye TEXTAREA'nın yerine koyar. Sayfa yenilenirse, yeni açıklama veritabanından "düzenlemek için tıkla" seçeneğiyle görüntülenir. Bugünlerde oldukça standart web 2.0 şeyler.

Sorun şu ki:

  1. sayfa açıklama olmadan yüklendi
  2. kullanıcı tarafından bir açıklama eklendi
  3. sayfadan bir bağlantıya tıklanarak yönlendirilir
  4. kullanıcı geri düğmesini tıklar

Daha sonra (tarayıcının önbelleğinden) görüntülenen, yeni açıklamayı içeren dinamik olarak değiştirilmiş DIV içermeyen sayfanın sürümüdür.

Kullanıcı güncellemelerinin kaybolduğunu varsaydığı ve değişiklikleri görmek için sayfayı yenilemeleri gerektiğini anlamayacağı için bu oldukça büyük bir sorundur.

Öyleyse, soru şudur: Yüklendikten sonra bir sayfayı değiştirilmiş olarak işaretleyebilir ve daha sonra kullanıcının "ona geri döndüğünü" algılayıp bu durumda yenilemeye zorlayabilirsiniz?


Bunun, aktardığınız sorudan farkı nedir?
innaM

soru benzer, ama bence ortam ve dolayısıyla cevap farklı, yanılıyor olabilirim. Diğer çözümle çözülebilecek bir sorunun ne olabileceğine dair yorumum şudur: kullanıcı ajax tarafından yüklenen bir sayfadaki bir sekmeyi, ardından başka bir sekmeyi vb. tıklar. geri düğmesini tıkladığınızda, önceki sekmeye değil, farklı bir sayfaya geri dönersiniz. "sayfa geçmişi" içindeki "ajax geçmişi" içinde geri dönmek istiyorlar. en azından Yahoo Tarayıcı Geçmişi Yöneticisinin ne yapması gerektiğine dair izlenimim bu. biraz daha basit bir şeyin peşindeydim.
Tom

Kabul edilen yanıt, iframe numaranızı içerir.
innaM

Yanıtlar:


79

Gizli bir form kullanın. Bir sayfaya geri dönmek için yeniden yüklediğinizde veya geri düğmesine bastığınızda, form verileri tarayıcılarda (genellikle) korunur. Aşağıdakiler sayfanıza girer (muhtemelen en alta yakın):

<form name="ignore_me">
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>

Javascript'inizde şunlara ihtiyacınız olacak:

var dirty_bit = document.getElementById('page_is_dirty');
if (dirty_bit.value == '1') window.location.reload();
function mark_page_dirty() {
    dirty_bit.value = '1';
}

Formu koklayan js, html tamamen ayrıştırıldıktan sonra çalıştırılmalıdır, ancak kullanıcı gecikmesi ciddi bir sorunsa, hem formu hem de js'yi sayfanın üst kısmına (js saniye) satır içi olarak koyabilirsiniz.


5
"Form verileri (tipik olarak) tarayıcılarda korunur" - bunu genişletebiliyor musunuz? bazı tarayıcılarda korunmuyor mu? veya bazı durumlarda?
Tom

4
Aslında, bunun yanlış gitmesi için düşünebileceğim tüm yolları listeleyeyim. (1) Opera, sayfanın tam durumunu korur ve js'yi yeniden çalıştırmaz. (2) Önbellek ayarlarınız, sayfayı sunucudan geri düğmesiyle yüklenmeye zorlarsa, form verileri kaybolabilir, bu da bu sorunun amaçları için uygundur. (3) Telefon tarayıcılarının önbelleği çok daha küçüktür ve tarayıcı sayfayı önceden önbellekten çıkarmış olabilir (bu amaçlar için bir sorun değildir).
Nick White

10
Bazı tarayıcılarda gizli etiketler korunmaz. Böylece, gizli giriş etiketi kullanmak yerine gizli metin etiketi kullanabilirsiniz. <input type = "text" value = "0" id = 'txt' name = 'txt' style = "display: none" />
sajith

2
Bu benim için harika çalıştı. Eminim çöktüğü durumlar vardır, ancak bu sorun için her çözüm olacaktır.
Joren

Safari tarayıcısı olan iPhone üzerinde çalışmıyor, deneyin, geri butonuna tıkladığınızda js tekrar çağrılmıyor.
woheras

54

İşte bu eski soruna çok kolay ve modern bir çözüm.

if (window.performance && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) {
    alert('Got here using the browser "Back" or "Forward" button.');
}

window.performance şu anda tüm büyük tarayıcılar tarafından desteklenmektedir.


Bunu duymamıştım. Bu dokümantasyonu yeni buldum ( developer.mozilla.org/en-US/docs/Web/API/Performance/navigation ) ve detaylandırdığınızı duymak isterim (örneğin neden window.performance && window.performance.navigation.typesadece yerine ihtiyaç var window.performance.navigation.TYPE_BACK_FORWARD?).
Ryan

5
window.performance.navigation.TYPE_BACK_FORWARDher zaman 2'ye eşit olan bir sabittir. Yani sadece karşılaştırma için kullanılır.
Bassem

Performance.navigation, andorid ve opera mini hariç tüm cihazlarda destekleniyor, ancak sorun yok çok güzel ( developer.mozilla.org/en-US/docs/Web/API/Performance/navigation )
Elbaz

1
Görünüşe performance.navigationgöre kullanımdan kaldırılmış ve bunun yerine developer.mozilla.org/en-US/docs/Web/API/…
RubberDuckRabbit

1
Firefox v70, 2geri düğmesi isabetleri için performance.navigation = destekleyecektir . V70'e kadar, yanlış bir şekilde geri döndü 1.
Andy Mercer

13

Bu makale bunu açıklıyor. Aşağıdaki koda bakın: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

<html>
    <head>
        <script>

            function pageShown(evt){
                if (evt.persisted) {
                    alert("pageshow event handler called.  The page was just restored from the Page Cache (eg. From the Back button.");
                } else {
                    alert("pageshow event handler called for the initial load.  This is the same as the load event.");
                }
            }

            function pageHidden(evt){
                if (evt.persisted) {
                    alert("pagehide event handler called.  The page was suspended and placed into the Page Cache.");
                } else {
                    alert("pagehide event handler called for page destruction.  This is the same as the unload event.");
                }
            }

            window.addEventListener("pageshow", pageShown, false);
            window.addEventListener("pagehide", pageHidden, false);

        </script>
    </head>
    <body>
        <a href="http://www.webkit.org/">Click for WebKit</a>
    </body>
</html>

1
Bu iyi bir cevap, en son Chrome 40 / Firefox 35'te çalışıyor. Yine de IE11 bu olayları desteklemiyor.
Slava Abakumov

Caniuse.com/#feat=page-transition-events'e göre, sayfa geçiş etkinlikleri aslında IE11 + 'da destekleniyor. Konuştuğumuz gibi, bu özelliğin% 88 oranında küresel kapsama alanı var
Cristian

Bilginize, Chrome geri düğmesine basıldığında bile event.persisted= döndürür false. window.performance.navigationChrome için PerformanceNavigationTiming'i kullanmalısınız .
Andy Mercer

4

Modern tarayıcılar için şu anda doğru yol bu gibi görünüyor:

const perfEntries = performance.getEntriesByType('navigation');
if (perfEntries.length && perfEntries[0].type === 'back_forward') {
  console.log('User got here from Back or Forward button.');
}

Bu, Ocak 2020 itibariyle hala "Deneysel", ancak iyi bir şekilde desteklendiği görülüyor.

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming


1
== yerine === kullanmak daha iyi
Aboozar Rajabi

2

Yukarıda belirtildiği gibi, bir çözüm buldum ve bunu referans ve geri bildirim için burada yayınlıyorum.

Çözümün ilk aşaması aşağıdakileri sayfaya eklemektir:

<!-- at the top of the content page -->
<IFRAME id="page_is_fresh" src="fresh.html" style="display:none;"></IFRAME>
<SCRIPT style="text/javascript">
  function reload_stale_page() { location.reload(); }
</SCRIPT>

İçeriği fresh.htmlönemli değildir, bu nedenle aşağıdakiler yeterli olmalıdır:

<!-- fresh.html -->
<HTML><BODY></BODY></HTML>

İstemci tarafı kodu sayfayı güncellediğinde, değişikliği aşağıdaki gibi işaretlemesi gerekir:

function trigger_reload_if_user_clicks_back_button()
{
  // "dis-arm" the reload stale page function so it doesn't fire  
  // until the page is reloaded from the browser's cache
  window.reload_stale_page = function(){};

  // change the IFRAME to point to a page that will reload the 
  // page when it loads
  document.getElementById("page_is_fresh").src = "stale.html";
}

stale.htmltüm işi yapar: Yüklendiğinde reload_stale_page, gerekirse sayfayı yenileyecek işlevi çağıracaktır . İlk kez yüklendiğinde (yani değişiklik yapıldıktan sonra reload_stale_pageişlev hiçbir şey yapmaz.)

<!-- stale.html -->
<HTML><BODY>
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT>
</BODY></HTML>

Bu aşamadaki (minimum) testime göre, bu arzu edildiği gibi çalışıyor gibi görünüyor. Herhangi bir şeyi gözden kaçırdım mı?


Bildiğimden değil ama tam olarak test etmedim. getElementById bazı eski tarayıcılarda desteklenmez, ancak gerekirse jquery veya başka bir şeyle değiştirmek kolaydır.
Tom

2

Onbeforeunload olayını kullanarak çözebilirsiniz :

window.onbeforeunload = function () { }

Onbeforeunload boş olay yöneticisi işlevine sahip olmak , sayfanın her erişildiğinde yeniden oluşturulacağı anlamına gelir. Javascripts yeniden çalıştırılacak, sunucu tarafındaki komut dosyaları yeniden çalıştırılacak, sayfa kullanıcı sayfaya ilk kez vuruyormuş gibi oluşturulacak, kullanıcı sayfaya sadece geri veya ileri düğmesine basarak gelse bile .

İşte bir örneğin tam kodu:

<html>
<head>
<title>onbeforeunload.html</title>
<script>
window.onbeforeunload = function () { }

function myfun()
{
   alert("The page has been refreshed.");
}
</script>

<body onload="myfun()">

Hello World!<br>

</body>
</html>

Deneyin, bu sayfadan ayrılın ve ardından tarayıcınızdaki "Geri" veya "İleri" düğmelerini kullanarak geri dönün.

IE, FF ve Chrome'da iyi çalışıyor.

Elbette myfun işlevi içinde ne isterseniz yapabilirsiniz .

Daha fazla bilgi: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript


Benim için Safari'de çalışıyor
Jakob


1

Bu sayfayı kullanarak, özellikle @ Nick White'ın yanıtıyla ilgili @sajith'in yorumunu ve bu sayfayı kullanarak: http://www.mrc-productivity.com/techblog/?p=1235

<form name="ignore_me" style="display:none">
    <input type="text" id="reloadValue" name="reloadValue" value="" />
</form>

$(function ()
{
    var date = new Date();
    var time = date.getTime();

    if ($("#reloadValue").val().length === 0)
    {
        $("#reloadValue").val(time);
    }
    else
    {
        $("#reloadValue").val("");
        window.location.reload();
    }
});

1

İşte bir jQuery sürümü. Bir kullanıcı geri düğmesine bastığında Safari masaüstü / mobil cihazının önbelleği işleme biçimi nedeniyle birkaç kez kullanma ihtiyacıyla karşılaştım.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        // Loading from cache
    }
});

1
Anladığım kadarıyla Chrome'da çalışmıyor gibi görünüyor. Bir console.log, sayfaya nasıl eriştiğimden bağımsız olarak, yalnızca else ifadesinde (test için eklenir) tetiklenir.
Luke

0

Bugün benzer bir sorunla karşılaştım ve bunu localStorage ile çözdüm (burada biraz jQuery ile):

$(function() {

    if ($('#page1').length) {
        // this code must only run on page 1

        var checkSteps = function () {
            if (localStorage.getItem('steps') == 'step2') {
                // if we are here, we know that:
                // 1. the user is on page 1
                // 2. he has been on page 2
                // 3. this function is running, which means the user has submitted the form
                // 4. but steps == step2, which is impossible if the user has *just* submitted the form
                // therefore we know that he has come back, probably using the back button of his browser
                alert('oh hey, welcome back!');
            } else {
                setTimeout(checkSteps, 100);
            }
        };

        $('#form').on('submit', function (e) {
            e.preventDefault();
            localStorage.setItem('steps', 'step1'); // if "step1", then we know the user has submitted the form
            checkOrderSteps();
            // ... then do what you need to submit the form and load page 2
        });
    }

    if ($('#page2').length) {
        // this code must only run on page 2
        localStorage.setItem('steps', 'step2');
    }

});

Si temelde:

1. sayfada, kullanıcı formu gönderdiğinde, kullanıcının hangi adımı attığını belirtmek için localStorage'da bir değer "adımlar" belirleriz. Aynı zamanda, bu değerin değiştirilip değiştirilmediğini kontrol edecek (örneğin, saniyede 10 kez) zaman aşımına sahip bir işlev başlatırız.

2. sayfada söz konusu değeri hemen değiştiriyoruz.

Dolayısıyla, kullanıcı geri düğmesini kullanırsa ve tarayıcı sayfa 1'i bıraktığımızdaki haline geri yüklerse, checkSteps işlevi hala çalışıyor ve localStorage'daki değerin değiştirildiğini algılayabiliyor (ve uygun eylemi gerçekleştirebiliyor) ). Bu kontrol bir kez amacını yerine getirdiğinde, onu çalıştırmaya devam etmemize gerek yoktur, bu yüzden artık setTimeout'u kullanmıyoruz.

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.