我一直在努力寻找解决我问题的简单方法。我有一个单页静态网站(请参见操作here)。每个视图都由一个哈希片段(用于直接链接)标识,并且HTML具有与哈希片段的锚链接,作为href,用于在视图之间导航。
我想要后退按钮的自定义行为。该网站具有层次结构,而不是迭代所有以前访问的视图,我希望后退按钮在层次结构中向上移动,然后将网站移至历史上其他任何位置。
经过多次迭代,我在下面共享的代码确实满足了这些要求,但是我想知道这是否是最简单的方法...
最终解决我的问题的诀窍归结为:
不构建 no 历史记录堆栈,但对所有导航使用replaceState
方法。仅在初始化期间,才需要一个pushState
来防止在第一次按下后退按钮时离开页面
捕获点击事件,不要让浏览器处理导航(因为它会建立历史记录)
捕获popstate事件(=后退按钮)以实现自定义行为,并在此处理程序中,确保当您不想将页面留在下一个页面时,发出新的pushState
后退按钮按下
这是我的代码:
// Single page static website
// with collapsible content in a two-level hierarchy
// three levels of detail:
// 0. the h1 headers are displayed, all are collapsed
// 1. one h1 header is expanded, showing the contained h2 headers
// 2. one h2 header is expanded, showing the contained content
// The user navigates the site by the provided anchor links,
// expanding or callapsing headings to change the level of detail,
// or by pressing the back button
// The back button doesn't go to the previous state,
// but moves the view one level up in the hierarchy,
// collapsing the current level of detail.
// When the top level is reached, the back button will leave the site.
// This avoids the user being 'trapped' in the site after a lot of
// navigation and allow him to leave the site by pressing the back
// button no more than 3 times.
var expansion = 0; // keep track of the current level of detail
var history_back = 1; // keep track of the history stack
// Functions to take care of everything that must happen upon navigation:
// changing the page view and updating the history.
// Note that no actual history stack is being built,
// replaceState is called to update the title and the hash fragment
function headerOnClick(header) {
expansion = 0;
// [code to change the page view]
// update history
window.history.replaceState({}, "Katholieke Gebeden", "#");
}
function h1OnClick(h1) {
expansion = 1;
// [code to change the page view]
// update history
window.history.replaceState({}, "Katholieke Gebeden" + $(h1).text(), "#" + $(h1).attr('id'));
}
function h2OnClick(h2) {
expansion = 2;
// [code to change the page view]
// update history
window.history.replaceState({}, "Katholieke Gebeden" + $(h2).text(), "#" + $(h2).attr('id'));
}
}
// Initialization
$(function() {
// function to dispatch navigation action to the proper function
var navigateToHash = function(hash) {
if (hash && hash != '#') {
var presetHeader = $(hash);
if (presetHeader.is('h1')) {
h1OnClick(presetHeader);
} else {
h2OnClick(presetHeader);
}
} else {
headerOnClick($('header'));
}
};
// on initialization, push the initial state once,
// otherwise the first back button will leave the page
window.history.pushState({}, window.document.title, window.location.hash);
// navigate to the initial view
// (e.g. when been called with hash fragment in the URL)
navigateToHash(window.location.hash);
// handle the back button
$(window).on('popstate', function(event) {
// keep track of the history stack
history_back -= 1;
if (expansion >= 1 && history_back < 1) {
// if expansion >= 1, push the history,
// so people won't leave the site when pushing back
// if expansion = 0, don't push the history,
// otherwise people won't be able to leave the site
window.history.pushState({}, window.document.title, window.location.hash);
history_back += 1;
}
if (expansion == 2) {
// find the parent h1 and navigate there
var openH1 = $('h1.selected');
navigateToHash("#" + openH1.attr('id'));
} else if (expansion == 1) {
// collapse everything
navigateToHash("#");
} else { // expansion == 0
// allow browser to leave the site
}
return false;
});
// handle the user performing a navigation
$('body').on('click', 'a[href*="#"]', function(event) {
// prevent the browser doing the navigation and updating the history
event.preventDefault();
navigateToHash(this.hash);
return false;
});
});