(Not: Sharky'nin geri bildirimlerine göre, arka alanları algılamak için kod ekledim)
Yani, bu soruları SO'da sık sık gördüm ve son zamanlarda geri düğmesi işlevselliğini kendim kontrol etme sorunuyla karşılaştım. Uygulamam için en iyi çözümü (Hash Navigation ile Tek Sayfa) aradıktan birkaç gün sonra, geri düğmesini algılamak için basit, çapraz tarayıcı, kitaplıksız bir sistem buldum.
Çoğu kişi şunları kullanmanızı önerir:
window.onhashchange = function() {
//blah blah blah
}
Ancak, bu işlev, kullanıcı konum karmasını değiştiren sayfa içi öğeyi kullandığında da çağrılır. Kullanıcınız tıkladığında ve sayfa ileri veya geri gittiğinde en iyi kullanıcı deneyimi olmaz.
Size sistemimin genel bir taslağını vermek için, kullanıcı arayüzde ilerledikçe önceki karmaları içeren bir dizi dolduruyorum. Şuna benziyor:
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
Oldukça düz ileri. Bunu çapraz tarayıcı desteğinin yanı sıra eski tarayıcılar için de destek sağlamak amacıyla yapıyorum. Yeni karmayı işleve iletmeniz yeterlidir ve sizin için saklar ve ardından karmayı değiştirir (bu daha sonra tarayıcının geçmişine konur).
Ayrıca lasthash
diziyi kullanarak kullanıcıyı sayfalar arasında hareket ettiren bir sayfa içi geri düğmesi de kullanıyorum . Şöyle görünüyor:
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
Yani bu kullanıcıyı son karmaya geri taşıyacak ve son karmayı diziden kaldıracağım (şu anda ileri düğmesi yok).
Yani. Bir kullanıcının sayfa içi geri düğmemi mi yoksa tarayıcı düğmesini mi kullandığını nasıl anlarım?
İlk başta baktım window.onbeforeunload
, ama boşuna - bu sadece kullanıcı sayfaları değiştirecekse çağrılır. Bu, karma gezinme kullanan tek sayfalık bir uygulamada gerçekleşmez.
Böylece, biraz daha kazdıktan sonra, bir bayrak değişkeni ayarlamaya çalışmak için öneriler gördüm. Benim durumumda bu, onu ayarlamaya çalışacağım, ama her şey asenkron olduğundan, her zaman karma değişikliği if deyimi için zamanında ayarlanmazdı. .onMouseDown
her zaman tıklamada çağrılmadı ve bir onclick'e eklemek hiçbir zaman yeterince hızlı tetiklemeyecekti.
Bu document
, ve arasındaki farka bakmaya başladığım zamandı window
. Son çözümüm bayrağı kullanarak ayarlamak document.onmouseover
ve devre dışı bırakmaktı document.onmouseleave
.
Kullanıcının faresi belge alanının içindeyken (okuyun: işlenen sayfa, ancak tarayıcı çerçevesi hariç), boolean'ım olarak ayarlandı true
. Fare belge alanından ayrılır ayrılmaz boole çevrilir false
.
Bu şekilde, benim window.onhashchange
:
window.onhashchange = function() {
if (window.innerDocClick) {
window.innerDocClick = false;
} else {
if (window.location.hash != '#undefined') {
goBack();
} else {
history.pushState("", document.title, window.location.pathname);
location.reload();
}
}
}
Çeki not edeceksiniz #undefined
. Bunun nedeni, dizimde hiçbir geçmişin olmaması durumunda geri dönmesidir undefined
. Bunu kullanıcıya bir window.onbeforeunload
olay kullanarak ayrılmak isteyip istemediklerini sormak için kullanıyorum .
Kısacası, geçmişi depolamak için bir sayfa içi geri düğmesi veya bir dizi kullanması gerekmeyen insanlar için:
document.onmouseover = function() {
//User's mouse is inside the page.
window.innerDocClick = true;
}
document.onmouseleave = function() {
//User's mouse has left the page.
window.innerDocClick = false;
}
window.onhashchange = function() {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back button was clicked
}
}
İşte buyur. karma gezinme ile ilgili sayfa içi öğelere karşı geri düğmesi kullanımını algılamanın basit, üç bölümlü bir yolu.
DÜZENLE:
Kullanıcının back olayını tetiklemek için backspace kullanmadığından emin olmak için aşağıdakileri de ekleyebilirsiniz ( Bu Soru'daki @thetoolman sayesinde ):
$(function(){
/*
* this swallows backspace keys on any non-input element.
* stops backspace -> back
*/
var rx = /INPUT|SELECT|TEXTAREA/i;
$(document).bind("keydown keypress", function(e){
if( e.which == 8 ){ // 8 == backspace
if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
e.preventDefault();
}
}
});
});