Tek sayfalık uygulamaların oluşturulmasını tamamen yeni bir API ile standart hale getirerek istemci tarafı yönlendirmeyi standart hale getiriyor.
Tek sayfalı uygulamalar (SPA'lar) temel bir özellikle tanımlanır: Varsayılan yöntem olan sunucudan tamamen yeni sayfalar yüklemek yerine, kullanıcı siteyle etkileşim kurarken içeriğini dinamik olarak yeniden yazar.
SPA'lar, History API aracılığıyla (veya sınırlı durumlarda sitenin #hash bölümünü ayarlayarak) bu özelliği sunabilse de History API, SPA'ların yaygınlaşmasından çok önce geliştirilmiş hantal bir API'dir ve web'de tamamen yeni bir yaklaşıma ihtiyaç duyulmaktadır. Navigation API, History API'nin eksikliklerini gidermek yerine bu alanı tamamen yenileyen önerilen bir API'dir. (Örneğin, Kaydırma Geri Yükleme, History API'yi yeniden icat etmek yerine bu API'ye bir yama uyguladı.)
Bu yayında, Gezinme API'si genel hatlarıyla açıklanmaktadır. Teknik öneriyi okumak için WICG deposundaki taslak raporu inceleyin.
Örnek kullanım
Navigation API'yi kullanmak için global navigation
nesnesine bir "navigate"
dinleyici ekleyerek başlayın.
Bu etkinlik temel olarak merkezidir: Kullanıcı bir işlem gerçekleştirdiğinde (ör.bağlantı tıklama, form gönderme veya geri ve ileri gitme) ya da gezinme programlı olarak tetiklendiğinde (ör. sitenizin kodu aracılığıyla) tüm gezinme türleri için etkinleştirilir.
Çoğu durumda, kodunuzun tarayıcının ilgili işlem için varsayılan davranışını geçersiz kılmasına olanak tanır.
SPA'lar için bu, muhtemelen kullanıcıyı aynı sayfada tutmak ve sitenin içeriğini yüklemek veya değiştirmek anlamına gelir.
"navigate"
dinleyicisine, hedef URL gibi gezinmeyle ilgili bilgileri içeren ve gezinmeye tek bir merkezi yerden yanıt vermenize olanak tanıyan bir NavigateEvent
iletilir.
Temel bir "navigate"
dinleyicisi şu şekilde görünebilir:
navigation.addEventListener('navigate', navigateEvent => {
// Exit early if this navigation shouldn't be intercepted.
// The properties to look at are discussed later in the article.
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname === '/') {
navigateEvent.intercept({handler: loadIndexPage});
} else if (url.pathname === '/cats/') {
navigateEvent.intercept({handler: loadCatsPage});
}
});
Gezinmeyle ilgili işlemleri iki şekilde yapabilirsiniz:
- Gezinmeyi yönetmek için
intercept({ handler })
(yukarıda açıklandığı gibi) çağrılıyor. preventDefault()
çağrısı yaparak navigasyonu tamamen iptal edebilirsiniz.
Bu örnekte, etkinlikte intercept()
çağrısı yapılmaktadır.
Tarayıcı, sitenizin sonraki durumunu yapılandırması gereken handler
geri çağırma işlevinizi çağırır.
Bu işlem, diğer kodun gezinme işleminin ilerleme durumunu izlemek için kullanabileceği bir geçiş nesnesi (navigation.transition
) oluşturur.
Genellikle hem intercept()
hem de preventDefault()
'e izin verilir ancak çağrılamayacakları durumlar da vardır.
Gezinme kaynaktan farklı bir kaynaktaysa intercept()
aracılığıyla gezinmeleri işleyemezsiniz.
Ayrıca, kullanıcı tarayıcısında Geri veya İleri düğmelerine basıyorsa preventDefault()
aracılığıyla gezinmeyi iptal edemezsiniz. Kullanıcılarınızı sitenizde tutamamanız gerekir.
(Bu konu GitHub'da tartışılıyor.)
Navigasyonu durduramaz veya durduramazsanız bile "navigate"
etkinliği tetiklenir.
Bilgilendirici olduğundan kodunuz, örneğin bir kullanıcının sitenizden ayrıldığını belirtmek için bir Analytics etkinliği günlüğe kaydedebilir.
Platforma neden başka bir etkinlik eklemelisiniz?
"navigate"
etkinlik işleyici, URL değişikliklerini SPA'da merkezileştirir.
Bu, eski API'leri kullananlar için zor bir tekliftir.
History API'yi kullanarak kendi SPA'nızın yönlendirmesini yazdıysanız aşağıdaki gibi bir kod eklemiş olabilirsiniz:
function updatePage(event) {
event.preventDefault(); // we're handling this link
window.history.pushState(null, '', event.target.href);
// TODO: set up page based on new URL
}
const links = [...document.querySelectorAll('a[href]')];
links.forEach(link => link.addEventListener('click', updatePage));
Bu iyi bir başlangıç olsa da yeterli değildir. Sayfanızdaki bağlantılar zaman içinde değişebilir. Ayrıca, kullanıcıların sayfalar arasında gezinmesinin tek yolu bağlantılar değildir. Örneğin, bir form gönderebilir veya hatta resim haritası kullanabilirler. Sayfanız bu işlemleri gerçekleştirebilir ancak basitleştirilebilecek çok sayıda olasılık vardır. Yeni Navigation API, bu olasılıkları basitleştirir.
Ayrıca, yukarıdaki yöntem geri/ileri gezinmeyi desteklemez. Bunun için başka bir etkinlik var "popstate"
.
Kişisel olarak, History API'nin bu olasılıklara yardımcı olabileceğini düşünüyorum.
Ancak aslında yalnızca iki yüzey alanı vardır: Kullanıcının tarayıcısında Geri veya İleri tuşuna basması durumunda yanıt verme ve URL'leri gönderme ve değiştirme. Yukarıda gösterildiği gibi, tıklama etkinlikleri için dinleyicileri manuel olarak ayarlamanız dışında "navigate"
ile benzerliği yoktur.
Gezinme öğelerini nasıl ele alacağınıza karar verme
navigateEvent
, belirli bir gezinmeyle nasıl başa çıkacağınıza karar vermek için kullanabileceğiniz gezinme hakkında birçok bilgi içerir.
Temel özellikler şunlardır:
canIntercept
- Bu değer yanlışsa gezinme işlemine müdahale edemezsiniz. Kaynaklar arası gezinmeler ve dokümanlar arası geçişler engellenemez.
destination.url
- Gezinmeyle ilgili dikkate almanız gereken en önemli bilgi muhtemelen budur.
hashChange
- Gezinme aynı dokümandaysa ve karma oluşturma işlemi, URL'nin mevcut URL'den farklı olan tek parçasıysa doğru değerini döndürür.
Modern SPA'larda karma oluşturma işlemi, geçerli belgenin farklı bölümlerine bağlantı oluşturmak için kullanılmalıdır. Dolayısıyla,
hashChange
doğruysa bu gezinme işlemini durdurmanıza muhtemelen gerek yoktur. downloadRequest
- Bu doğruysa gezinme,
download
özelliğine sahip bir bağlantı tarafından başlatılmıştır. Çoğu durumda bu işlemi durdurmanız gerekmez. formData
- Bu değer null değilse bu gezinme, POST form gönderme işleminin bir parçasıdır.
Gezinme sırasında bunu göz önünde bulundurun.
Yalnızca GET gezinmelerini işlemek istiyorsanız
formData
değerinin null olmadığı gezinmelerin yolunu kesmekten kaçının. Makalenin ilerleyen bölümlerinde form gönderimlerini işlemeyle ilgili örneği inceleyin. navigationType
- Bu,
"reload"
,"push"
,"replace"
veya"traverse"
değerlerinden biridir."traverse"
ise bu gezinmepreventDefault()
üzerinden iptal edilemez.
Örneğin, ilk örnekte kullanılan shouldNotIntercept
işlevi şöyle olabilir:
function shouldNotIntercept(navigationEvent) {
return (
!navigationEvent.canIntercept ||
// If this is just a hashChange,
// just let the browser handle scrolling to the content.
navigationEvent.hashChange ||
// If this is a download,
// let the browser perform the download.
navigationEvent.downloadRequest ||
// If this is a form submission,
// let that go to the server.
navigationEvent.formData
);
}
Araya girme
Kodunuz "navigate"
dinleyicisinden intercept({ handler })
'ü çağrdığında, sayfayı yeni ve güncellenmiş duruma hazırladığını ve gezinmenin biraz zaman alabileceğini tarayıcıya bildirir.
Tarayıcı, mevcut durumun kaydırma konumunu yakalayarak başlar. Böylece, isteğe bağlı olarak daha sonra geri yüklenebilir. Ardından handler
geri çağırma işlevinizi çağırır.
handler
işleviniz bir promise döndürüyorsa (asynchronize işlevlerde bu otomatik olarak gerçekleşir) bu promise tarayıcıya gezinmenin ne kadar sürdüğünü ve başarılı olup olmadığını bildirir.
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
},
});
}
});
Bu nedenle bu API, tarayıcının anladığı semantik bir kavram sunar: Şu anda bir SPA gezinmesi gerçekleşmektedir. Bu gezinme, zaman içinde dokümanı önceki URL'den ve durumdan yeni bir URL'ye ve duruma değiştirir. Bu, erişilebilirlik de dahil olmak üzere çeşitli potansiyel avantajlara sahiptir: Tarayıcılar, gezinmenin başlangıcını, sonunu veya olası hatasını gösterebilir. Örneğin Chrome, yerel yükleme göstergesini etkinleştirir ve kullanıcının durdur düğmesiyle etkileşime geçmesine olanak tanır. (Bu durum, kullanıcı geri/ileri düğmelerini kullanarak gezinirken şu anda gerçekleşmiyor ancak yakında düzeltilecek.)
Gezinme işlemini tamamlama
Gezinme işlemlerine müdahale edildiğinde yeni URL, handler
geri çağırma işleviniz çağrılmadan hemen önce geçerli olur.
DOM'u hemen güncellemezseniz eski içeriğin yeni URL ile birlikte gösterildiği bir dönem oluşur.
Bu durum, veri alırken veya yeni alt kaynaklar yüklerken göreli URL çözümü gibi işlemleri etkiler.
URL değişikliğini erteleme yöntemi GitHub'da tartışılmaktadır ancak genellikle sayfayı, gelen içerik için bir tür yer tutucu ile hemen güncellemeniz önerilir:
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
// The URL has already changed, so quickly show a placeholder.
renderArticlePagePlaceholder();
// Then fetch the real data.
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
},
});
}
});
Bu, URL çözümleme sorunlarını önlemekle kalmaz, kullanıcıya anında yanıt verdiğiniz için hızlı bir deneyim de sunar.
İptal sinyalleri
intercept()
işleyicisinde eşzamansız çalışma yapabildiğiniz için gezinmenin gereksiz hale gelmesi mümkündür.
Bu durum aşağıdaki durumlarda ortaya çıkar:
- Kullanıcı başka bir bağlantıyı tıklar veya bazı kodlar başka bir gezinme işlemi gerçekleştirir. Bu durumda, eski gezinme menüsü yeni gezinme menüsü lehine terk edilir.
- Kullanıcı tarayıcıda "durdur" düğmesini tıklar.
Bu olasılıklardan herhangi biriyle başa çıkmak için "navigate"
dinleyicisine iletilen etkinlik, AbortSignal
olan bir signal
mülkü içerir.
Daha fazla bilgi için İptal edilebilir getirme bölümüne bakın.
Özetlemek gerekirse, temel olarak çalışmanızı durdurmanız gerektiğinde bir etkinlik tetikleyen bir nesne sağlar.
Özellikle, fetch()
adresine yaptığınız tüm aramalara bir AbortSignal
iletebilirsiniz. Bu, gezinme öncelikli hale getirilirse uçuş sırasındaki ağ isteklerini iptal eder.
Bu işlem hem kullanıcının bant genişliğini korur hem de fetch()
tarafından döndürülen Promise
öğesini reddeder. Böylece, sonraki kodların DOM'u geçersiz bir sayfa gezinmesi gösterecek şekilde güncellemesi gibi işlemleri engeller.
Aşağıda, önceki örnekte getArticleContent
satır içine yerleştirilmiş şekilde gösterilmektedir. Bu örnekte, AbortSignal
'un fetch()
ile nasıl kullanılabileceği gösterilmektedir:
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
// The URL has already changed, so quickly show a placeholder.
renderArticlePagePlaceholder();
// Then fetch the real data.
const articleContentURL = new URL(
'/get-article-content',
location.href
);
articleContentURL.searchParams.set('path', url.pathname);
const response = await fetch(articleContentURL, {
signal: navigateEvent.signal,
});
const articleContent = await response.json();
renderArticlePage(articleContent);
},
});
}
});
Kaydırma işleme
Bir navigasyonu intercept()
ettiğinizde tarayıcı, kaydırma işlemini otomatik olarak gerçekleştirmeye çalışır.
Yeni bir geçmiş girişine yapılan gezinmelerde (navigationEvent.navigationType
"push"
veya "replace"
olduğunda), bu, URL parçasıyla (#
'ten sonraki kısım) belirtilen bölüme kaydırmaya çalışma veya kaydırma çubuğunu sayfanın en üstüne sıfırlama anlamına gelir.
Yeniden yükleme ve geçişlerde bu, kaydırma konumunun bu geçmiş girişinin son kez görüntülendiği yere geri yükleneceği anlamına gelir.
Bu işlem varsayılan olarak, handler
tarafından döndürülen söz çözüldükten sonra gerçekleşir. Ancak daha önce kaydırmanın mantıklı olduğu durumlarda navigateEvent.scroll()
'ı çağırabilirsiniz:
navigation.addEventListener('navigate', navigateEvent => {
if (shouldNotIntercept(navigateEvent)) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith('/articles/')) {
navigateEvent.intercept({
async handler() {
const articleContent = await getArticleContent(url.pathname);
renderArticlePage(articleContent);
navigateEvent.scroll();
const secondaryContent = await getSecondaryContent(url.pathname);
addSecondaryContent(secondaryContent);
},
});
}
});
Alternatif olarak, intercept()
scroll
seçeneğini "manual"
olarak ayarlayarak otomatik kaydırma işlevini tamamen devre dışı bırakabilirsiniz:
navigateEvent.intercept({
scroll: 'manual',
async handler() {
// …
},
});
Odak işleme
handler
tarafından döndürülen söz çözüldükten sonra tarayıcı, autofocus
özelliği ayarlanmış ilk öğeyi veya bu özelliğe sahip öğe yoksa <body>
öğesini odaklar.
intercept()
için focusReset
seçeneğini "manual"
olarak ayarlayarak bu davranışı devre dışı bırakabilirsiniz:
navigateEvent.intercept({
focusReset: 'manual',
async handler() {
// …
},
});
Başarı ve başarısızlık etkinlikleri
intercept()
işleyiciniz çağrıldığında aşağıdaki iki durumdan biri gerçekleşir:
- Döndürülen
Promise
koşulu karşılıyorsa (veyaintercept()
çağrılmadıysa) Gezinme API'siEvent
ile"navigatesuccess"
'yi tetikler. - Döndürülen
Promise
reddederse API,"navigateerror"
'üErrorEvent
ile tetikler.
Bu etkinlikler, kodunuzun başarı veya başarısızlıkla merkezi bir şekilde ilgilenmesine olanak tanır. Örneğin, daha önce gösterilen bir ilerleme göstergesini gizleyerek başarıyı ele alabilirsiniz.
navigation.addEventListener('navigatesuccess', event => {
loadingIndicator.hidden = true;
});
Başarısızlık durumunda da bir hata mesajı gösterilebilir:
navigation.addEventListener('navigateerror', event => {
loadingIndicator.hidden = true; // also hide indicator
showMessage(`Failed to load page: ${event.message}`);
});
ErrorEvent
alan "navigateerror"
etkinlik dinleyicisi, yeni bir sayfa oluşturan kodunuzdan hata alacağı garanti edildiğinden özellikle kullanışlıdır.
Ağ kullanılamıyorsa hatanın "navigateerror"
adresine yönlendirileceğini bilerek await fetch()
yapabilirsiniz.
Gezinme girişleri
navigation.currentEntry
, geçerli girişe erişim sağlar.
Bu, kullanıcının şu anda nerede olduğunu açıklayan bir nesnedir.
Bu giriş, geçerli URL'yi, bu girişi zaman içinde tanımlamak için kullanılabilecek meta verileri ve geliştirici tarafından sağlanan durumu içerir.
Meta veriler, her girişin mevcut girişi ve yuvasını temsil eden benzersiz bir dize özelliği olan key
öğesini içerir.
Mevcut girişin URL'si veya durumu değişse bile bu anahtar aynı kalır.
Kart hâlâ aynı yuvada.
Buna karşılık, kullanıcı Geri tuşuna basıp aynı sayfayı yeniden açarsa bu yeni giriş yeni bir yuva oluşturduğundan key
değişir.
Gezinme API'si, kullanıcıyı doğrudan eşleşen bir anahtara sahip bir girişe yönlendirmenize olanak tanıdığından key
geliştiriciler için kullanışlıdır.
Sayfalar arasında kolayca atlamak için diğer girişlerin durumlarında bile bu düğmeyi basılı tutabilirsiniz.
// On JS startup, get the key of the first loaded page
// so the user can always go back there.
const {key} = navigation.currentEntry;
backToHomeButton.onclick = () => navigation.traverseTo(key);
// Navigate away, but the button will always work.
await navigation.navigate('/another_url').finished;
Eyalet
Navigation API, geliştirici tarafından sağlanan ve mevcut geçmiş girişinde kalıcı olarak depolanan ancak kullanıcı tarafından doğrudan görülemeyen "durum" bilgisini gösterir.
Bu, History API'deki history.state
işlevine çok benzer ancak ondan daha gelişmiştir.
Navigation API'de, geçerli girişin (veya herhangi bir girişin) .getState()
yöntemini çağırarak durumunun bir kopyasını döndürebilirsiniz:
console.log(navigation.currentEntry.getState());
Varsayılan olarak bu değer undefined
olur.
Ayar durumu
Durum nesneleri değiştirilebilir olsa da bu değişiklikler geçmiş girişiyle birlikte geri kaydedilmez. Bu nedenle:
const state = navigation.currentEntry.getState();
console.log(state.count); // 1
state.count++;
console.log(state.count); // 2
// But:
console.info(navigation.currentEntry.getState().count); // will still be 1
Durumu ayarlamak için doğru yöntem, komut dosyasında gezinme sırasındadır:
navigation.navigate(url, {state: newState});
// Or:
navigation.reload({state: newState});
Burada newState
, herhangi bir kopyalanabilir nesne olabilir.
Mevcut girişin durumunu güncellemek istiyorsanız en iyi yöntem, mevcut girişin yerini alacak bir gezinme gerçekleştirmektir:
navigation.navigate(location.href, {state: newState, history: 'replace'});
Ardından "navigate"
etkinlik dinleyiciniz, navigateEvent.destination
aracılığıyla bu değişikliği algılayabilir:
navigation.addEventListener('navigate', navigateEvent => {
console.log(navigateEvent.destination.getState());
});
Durumu senkronize olarak güncelleme
Genellikle durumu navigation.reload({state: newState})
aracılığıyla asenkron olarak güncellemek daha iyidir. Ardından "navigate"
dinleyiciniz bu durumu uygulayabilir. Ancak bazen durum değişikliği, kodunuz bu değişikliği öğrenene kadar zaten tamamen uygulanmış olur (ör. kullanıcı bir <details>
öğesini etkinleştirip devre dışı bıraktığında veya kullanıcı bir form girişinin durumunu değiştirdiğinde). Bu durumlarda, bu değişikliklerin yeniden yükleme ve geçiş işlemleri sırasında korunması için durumu güncelleyebilirsiniz. Bu işlem updateCurrentEntry()
kullanılarak yapılabilir:
navigation.updateCurrentEntry({state: newState});
Bu değişiklik hakkında bilgi edinmek için katılabileceğiniz bir etkinlik de düzenlenmektedir:
navigation.addEventListener('currententrychange', () => {
console.log(navigation.currentEntry.getState());
});
Ancak "currententrychange"
'te durum değişikliklerine tepki verdiğinizi fark ederseniz durum işleme kodunuzu "navigate"
etkinliği ile "currententrychange"
etkinliği arasında bölüyor veya hatta kopyalıyorsunuz demektir. navigation.reload({state: newState})
ise bu işlemi tek bir yerde yapmanıza olanak tanır.
Eyalet ve URL parametreleri
Durum, yapılandırılmış bir nesne olabileceğinden tüm uygulama durumunuz için kullanmak cazip gelebilir. Ancak çoğu durumda bu durumu URL'de depolamak daha iyidir.
Kullanıcı URL'yi başka bir kullanıcıyla paylaştığında durumun korunmasını istiyorsanız durumu URL'de saklayın. Aksi takdirde, durum nesnesi daha iyi bir seçenektir.
Tüm girişlere erişme
Ancak "mevcut giriş" bununla sınırlı değildir.
API, kullanıcının sitenizi kullanırken gezindiği girişlerin tamamına erişmenize de olanak tanır. Bunun için navigation.entries()
çağrısı kullanılır. Bu çağrı, girişlerin anlık görüntü dizisini döndürür.
Bu, örneğin, kullanıcının belirli bir sayfaya nasıl gittiğine bağlı olarak farklı bir kullanıcı arayüzü göstermek veya yalnızca önceki URL'lere ya da bunların durumlarına bakmak için kullanılabilir.
Mevcut History API ile bu işlem mümkün değildir.
Ayrıca, giriş artık tarayıcı geçmişinin bir parçası olmadığında tetiklenen NavigationHistoryEntry
'larda "dispose"
etkinliğini de dinleyebilirsiniz. Bu durum, genel temizlik kapsamında olabileceği gibi gezinirken de ortaya çıkabilir. Örneğin, 10 yer geri gidip ileri giderseniz bu 10 geçmiş girişi silinir.
Örnekler
"navigate"
etkinliği, yukarıda belirtildiği gibi tüm gezinme türleri için tetiklenir.
(Aslında, mümkün olan tüm türlerin spesifikasyonda yer aldığı uzun bir ek vardır.)
Birçok sitede en yaygın durum kullanıcının bir <a href="...">
tıklamasıdır. Bununla birlikte, ele alınması gereken iki önemli ve daha karmaşık gezinme türü vardır.
Programatik gezinme
İlki, istemci tarafı kodunuzdaki bir yöntem çağrısının neden olduğu programatik gezinmedir.
Gezinme işlemi başlatmak için kodunuzun herhangi bir yerinden navigation.navigate('/another_page')
işlevini çağırabilirsiniz.
Bu işlem, "navigate"
dinleyicisine kayıtlı merkezi etkinlik işleyici tarafından gerçekleştirilir ve merkezi dinleyiciniz senkronize olarak çağrılır.
Bu, location.assign()
ve arkadaşlar gibi eski yöntemlerin yanı sıra History API'nin pushState()
ve replaceState()
yöntemlerinin geliştirilmiş bir toplama işlemi olarak tasarlanmıştır.
navigation.navigate()
yöntemi, { committed, finished }
içinde iki Promise
örneği içeren bir nesne döndürür.
Bu sayede, çağıran, geçişin "taahhüt edilene" (görünür URL değişti ve yeni bir NavigationHistoryEntry
kullanılabilir) veya "tamamlanana" (intercept({ handler })
tarafından döndürülen tüm sözler tamamlandı veya başarısızlık ya da başka bir gezinme tarafından öncelik verilmesi nedeniyle reddedildi) kadar bekleyebilir.
navigate
yönteminde, aşağıdakileri ayarlayabileceğiniz bir options nesnesi de vardır:
state
:NavigationHistoryEntry
üzerindeki.getState()
yöntemi aracılığıyla kullanılabilen yeni geçmiş girişinin durumu.history
: Geçerli geçmiş girişini değiştirmek için"replace"
olarak ayarlanabilir.info
:navigateEvent.info
aracılığıyla gezinme etkinliğine iletilecek bir nesne.
Özellikle info
, örneğin bir sonraki sayfanın görünmesine neden olan belirli bir animasyonu belirtmek için yararlı olabilir.
(Alternatif olarak, global bir değişken ayarlayabilir veya #hash'in bir parçası olarak dahil edebilirsiniz. Her iki seçenek de biraz garip.)
Kullanıcı daha sonra Geri ve İleri düğmelerini kullanarak gezinme yaparsa bu info
yeniden oynatılmaz.
Aslında bu durumlarda her zaman undefined
olur.
navigation
, { committed, finished }
içeren bir nesne döndüren başka gezinme yöntemlerine de sahiptir.
traverseTo()
(kullanıcı geçmişindeki belirli bir girişi belirten bir key
kabul eder) ve navigate()
hakkında daha önce bahsetmiştik.
back()
, forward()
ve reload()
de bu kapsamdadır.
Bu yöntemlerin tümü, navigate()
gibi merkezi "navigate"
etkinlik işleyici tarafından işlenir.
Form Gönderimleri
İkinci olarak, POST aracılığıyla HTML <form>
gönderimi özel bir gezinme türüdür ve Navigation API bu işlemin önüne geçebilir.
Ek bir yükü olsa da gezinme, "navigate"
dinleyici tarafından merkezi olarak yönetilir.
Form gönderimi, NavigateEvent
üzerinde formData
mülkü aranarak algılanabilir.
Aşağıda, herhangi bir form gönderimini fetch()
aracılığıyla mevcut sayfada kalan bir gönderime dönüştüren bir örnek verilmiştir:
navigation.addEventListener('navigate', navigateEvent => {
if (navigateEvent.formData && navigateEvent.canIntercept) {
// User submitted a POST form to a same-domain URL
// (If canIntercept is false, the event is just informative:
// you can't intercept this request, although you could
// likely still call .preventDefault() to stop it completely).
navigateEvent.intercept({
// Since we don't update the DOM in this navigation,
// don't allow focus or scrolling to reset:
focusReset: 'manual',
scroll: 'manual',
handler() {
await fetch(navigateEvent.destination.url, {
method: 'POST',
body: navigateEvent.formData,
});
// You could navigate again with {history: 'replace'} to change the URL here,
// which might indicate "done"
},
});
}
});
Eksikler
"navigate"
etkinlik dinleyicisinin merkezi yapısına rağmen mevcut Navigation API spesifikasyonu, bir sayfanın ilk yüklenmesinde "navigate"
'ü tetiklemez.
Tüm durumlar için sunucu tarafı oluşturma (SSR) kullanan sitelerde bu sorun olmayabilir. Sunucunuz, kullanıcılarınıza içerik sunmanın en hızlı yolu olan doğru ilk durumu döndürebilir.
Ancak sayfalarını oluşturmak için istemci tarafı kodundan yararlanan sitelerin, sayfalarını başlatmak için ek bir işlev oluşturması gerekebilir.
Gezinme API'sinin bilinçli bir tasarım tercihi de yalnızca tek bir çerçevede (yani en üst düzey sayfa veya tek bir belirli <iframe>
) çalışmasıdır.
Bu, özellikte daha ayrıntılı olarak açıklanan bir dizi ilginç sonucun yanı sıra pratikte geliştiricilerin kafa karışıklığını azaltacaktır.
Önceki History API'de, çerçeve desteği gibi kafa karıştırıcı bazı uç durumlar vardır. Yeniden tasarlanan Navigation API ise bu uç durumları baştan ele alır.
Son olarak, kullanıcının gezindiği girişlerin listesini programatik olarak değiştirme veya yeniden düzenleme konusunda henüz bir fikir birliğine varılmadı. Bu konu şu anda tartışılıyor ancak yalnızca silme işlemlerine izin vermek (geçmiş girişler veya "gelecekteki tüm girişler") bir seçenek olabilir. İkincisi, geçici duruma izin verir. Örneğin, geliştirici olarak şunları yapabilirim:
- Yeni URL'ye veya duruma giderek kullanıcıya soru sorabilirsiniz.
- Kullanıcının işini tamamlamasına izin verin (veya Geri'ye gidin)
- Görev tamamlandığında geçmiş girişini kaldırma
Bu, geçici modallar veya geçiş reklamları için mükemmel olabilir: Yeni URL, kullanıcının Geri hareketini kullanarak ayrılabileceği bir URL'dir ancak kullanıcı, giriş kaldırıldığı için yanlışlıkla İleri'ye giderek URL'yi tekrar açamaz. Bu, mevcut History API ile mümkün değildir.
Navigation API'yi deneyin
Navigation API, Chrome 102'de flag olmadan kullanılabilir. Domenic Denicola tarafından hazırlanan bir demoyu da deneyebilirsiniz.
Klasik History API basit görünse de çok iyi tanımlanmamıştır ve uç durumlar ile tarayıcılar arasında farklı şekilde uygulanmasıyla ilgili çok sayıda soruna sahiptir. Yeni Navigation API ile ilgili geri bildirimde bulunacağınızı umuyoruz.
Referanslar
- WICG/navigation-api
- Mozilla Standartları Konumlandırması
- Prototip Oluşturma Amacı
- TAG incelemesi
- Chromestatus girişi
Teşekkür ederiz
Bu yayını inceleyen Thomas Steiner, Domenic Denicola ve Nate Chapin'e teşekkür ederiz.