chore(scroll): smarter scroll behavior (#744)

authored-by: Mate Solymosi <mate.solymosi.ext@siemens.com>
This commit is contained in:
Máté Solymosi 2020-03-09 09:53:08 +01:00 committed by GitHub
parent 291c99bc38
commit 0f1749cb66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 15 deletions

View File

@ -1,11 +1,26 @@
import { isMobile } from '../util/env';
import { body, on } from '../util/dom';
import * as sidebar from './sidebar';
import { scrollIntoView } from './scroll';
import { scrollIntoView, scroll2Top } from './scroll';
export function eventMixin(proto) {
proto.$resetEvents = function() {
scrollIntoView(this.route.path, this.route.query.id);
proto.$resetEvents = function(source) {
const { auto2top } = this.config;
(() => {
// Rely on the browser's scroll auto-restoration when going back or forward
if (source === 'history') {
return;
}
// Scroll to ID if specified
if (this.route.query.id) {
scrollIntoView(this.route.path, this.route.query.id);
}
// Scroll to top if a link was clicked and auto2top is enabled
if (source === 'navigate') {
auto2top && scroll2Top(auto2top);
}
})();
if (this.config.loadNavbar) {
sidebar.getAndActive(this.router, 'nav');

View File

@ -148,7 +148,10 @@ export function fetchMixin(proto) {
}
};
proto.$fetch = function(cb = noop) {
proto.$fetch = function(
cb = noop,
$resetEvents = this.$resetEvents.bind(this)
) {
const done = () => {
callHook(this, 'doneEach');
cb();
@ -160,7 +163,7 @@ export function fetchMixin(proto) {
done();
} else {
this._fetch(() => {
this.$resetEvents();
$resetEvents();
done();
});
}

View File

@ -7,7 +7,7 @@ import { getAndActive, sticky } from '../event/sidebar';
import { getPath, isAbsolutePath } from '../router/util';
import { isMobile, inBrowser } from '../util/env';
import { isPrimitive } from '../util/core';
import { scrollActiveSidebar, scroll2Top } from '../event/scroll';
import { scrollActiveSidebar } from '../event/scroll';
import { Compiler } from './compiler';
import * as tpl from './tpl';
import { prerenderEmbed } from './embed';
@ -123,7 +123,7 @@ export function renderMixin(proto) {
};
proto._bindEventOnRendered = function(activeEl) {
const { autoHeader, auto2top } = this.config;
const { autoHeader } = this.config;
scrollActiveSidebar(this.router);
@ -136,8 +136,6 @@ export function renderMixin(proto) {
dom.before(main, wrapper.children[0]);
}
}
auto2top && scroll2Top(auto2top);
};
proto._renderNav = function(text) {

View File

@ -30,7 +30,25 @@ export class HashHistory extends History {
}
onchange(cb = noop) {
on('hashchange', cb);
// The hashchange event does not tell us if it originated from
// a clicked link or by moving back/forward in the history;
// therefore we set a `navigating` flag when a link is clicked
// to be able to tell these two scenarios apart
let navigating = false;
on('click', e => {
const el = e.target.tagName === 'A' ? e.target : e.target.parentNode;
if (el.tagName === 'A' && !/_blank/.test(el.target)) {
navigating = true;
}
});
on('hashchange', e => {
const source = navigating ? 'navigate' : 'history';
navigating = false;
cb({ event: e, source });
});
}
normalize() {

View File

@ -28,11 +28,13 @@ export class HTML5History extends History {
e.preventDefault();
const url = el.href;
window.history.pushState({ key: url }, '', url);
cb();
cb({ event: e, source: 'navigate' });
}
});
on('popstate', cb);
on('popstate', e => {
cb({ event: e, source: 'history' });
});
}
/**

View File

@ -2,6 +2,7 @@ import { supportsPushState } from '../util/env';
import * as dom from '../util/dom';
import { HashHistory } from './history/hash';
import { HTML5History } from './history/html5';
import { noop } from '../util/core';
export function routerMixin(proto) {
proto.route = {};
@ -31,16 +32,16 @@ export function initRouter(vm) {
lastRoute = vm.route;
// eslint-disable-next-line no-unused-vars
router.onchange(_ => {
router.onchange(params => {
updateRender(vm);
vm._updateRender();
if (lastRoute.path === vm.route.path) {
vm.$resetEvents();
vm.$resetEvents(params.source);
return;
}
vm.$fetch();
vm.$fetch(noop, vm.$resetEvents.bind(vm, params.source));
lastRoute = vm.route;
});
}