mirror of
https://gitee.com/docsifyjs/docsify.git
synced 2024-12-02 20:20:30 +08:00
chore(scroll): smarter scroll behavior (#744)
authored-by: Mate Solymosi <mate.solymosi.ext@siemens.com>
This commit is contained in:
parent
291c99bc38
commit
0f1749cb66
@ -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');
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -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' });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user