update: Router will record scroll history and recovery.
This commit is contained in:
defaultkavy 2024-08-29 02:50:32 +08:00
parent aca5281285
commit 1111fc5e66
Signed by: defaultkavy
GPG Key ID: 59B28939E8FDD2CD
2 changed files with 60 additions and 6 deletions

View File

@ -11,6 +11,7 @@ export class Router {
events = new $EventManager<RouterEventMap>().register('notfound', 'load');
basePath: string;
static currentPath: URL = new URL(location.href);
static readonly SCROLL_HISTORY_KEY = '$router_scroll_history';
constructor(basePath: string, view?: $View) {
this.basePath = basePath;
this.$view = view ?? new $View();
@ -50,6 +51,7 @@ export class Router {
history.pushState(routeData, '', url);
Router.currentPath = new URL(location.href);
$.routers.forEach(router => router.resolvePath())
Router.recoveryScrollPosition();
Router.events.fire('pathchange', {prevURL: prevPath, nextURL: Router.currentPath, navigation: 'Forward'});
return this;
}
@ -91,6 +93,7 @@ export class Router {
const prevPath = Router.currentPath;
Router.index = history.state.index;
this.resolvePath();
Router.recoveryScrollPosition();
Router.currentPath = new URL(location.href);
Router.events.fire('pathchange', {prevURL: prevPath, nextURL: Router.currentPath, navigation: 'Forward'});
}).bind(this)
@ -170,6 +173,48 @@ export class Router {
}
}
static recoveryScrollPosition() {
const history = this.getScrollHistory(this.index, location.href);
if (!history) {
document.documentElement.scrollTop = 0;
this.setScrollHistory(this.index, location.href, 0);
}
else document.documentElement.scrollTop = history.scroll;
}
static getScrollHistory(pageIndex: number, href: string) {
const data = this.scrollHistoryData;
if (!data || !data[pageIndex]) return null;
return data[pageIndex].href === href ? data[pageIndex] : null;
}
static setScrollHistory(pageIndex: number, href: string, scroll: number) {
let history = this.scrollHistoryData;
if (!history) {
history = {[pageIndex]: {href, scroll}};
sessionStorage.setItem(this.SCROLL_HISTORY_KEY, JSON.stringify(history));
}
else {
const data = history[pageIndex];
if (data && data.href !== href) {
let i = 0;
while (history[pageIndex + i]) {
delete history[pageIndex + i];
i++;
}
}
history[pageIndex] = {href, scroll}
sessionStorage.setItem(this.SCROLL_HISTORY_KEY, JSON.stringify(history));
}
return history[pageIndex];
}
static get scrollHistoryData() {
const json = sessionStorage.getItem(this.SCROLL_HISTORY_KEY)
if (!json) return null;
return JSON.parse(json) as {[key: number]: RouteScrollHistoryData};
}
static on<K extends keyof RouterGlobalEventMap>(type: K, callback: (...args: RouterGlobalEventMap[K]) => any) { this.events.on(type, callback); return this }
static off<K extends keyof RouterGlobalEventMap>(type: K, callback: (...args: RouterGlobalEventMap[K]) => any) { this.events.off(type, callback); return this }
static once<K extends keyof RouterGlobalEventMap>(type: K, callback: (...args: RouterGlobalEventMap[K]) => any) { this.events.once(type, callback); return this }
@ -187,4 +232,13 @@ interface RouterGlobalEventMap {
type RouteData = {
index: number;
data: {[key: string]: any};
}
}
type RouteScrollHistoryData = {
href: string;
scroll: number;
}
window.addEventListener('scroll', () => {
Router.setScrollHistory(Router.index, location.href, document.documentElement.scrollTop);
})

View File

@ -1,21 +1,21 @@
{
"name": "@elexis/router",
"description": "A simple router for ElexisJS",
"version": "0.1.0",
"version": "0.1.1",
"author": {
"name": "defaultkavy",
"email": "defaultkavy@gmail.com",
"url": "https://github.com/defaultkavy"
"url": "https://git.defaultkavy.com/defaultkavy"
},
"repository": {
"type": "git",
"url": "git+https://github.com/elexis/router.git"
"url": "git+https://git.defaultkavy.com/elexis/router.git"
},
"module": "index.ts",
"bugs": {
"url": "https://github.com/elexis/router/issues"
"url": "https://git.defaultkavy.com/elexis/router/issues"
},
"homepage": "https://github.com/elexis/router",
"homepage": "https://git.defaultkavy.com/elexis/router",
"keywords": ["router", "web", "front-end", "lib", "fluent", "framework"],
"license": "ISC",
"type": "module",