跳到主要内容

React DOM 默认过渡指示器

export function defaultOnDefaultTransitionIndicator(): void | (() => void) {
if (typeof navigation !== 'object') {
// If the Navigation API is not available, then this is a noop.
// 如果导航 API 不可用,则此操作无效。
return;
}

let isCancelled = false;
let pendingResolve: null | (() => void) = null;

function handleNavigate(event: NavigateEvent) {
if (event.canIntercept && event.info === 'react-transition') {
event.intercept({
handler() {
return new Promise(resolve => (pendingResolve = resolve));
},
focusReset: 'manual',
scroll: 'manual',
});
}
}

function handleNavigateComplete() {
if (pendingResolve !== null) {
// If this was not our navigation completing, we were probably cancelled.
// We'll start a new one below.
// 如果这不是我们的导航完成,可能是被取消了。我们将在下面开始新的导航。
pendingResolve();
pendingResolve = null;
}
if (!isCancelled) {
// Some other navigation completed but we should still be running.
// Start another fake one to keep the loading indicator going.
// There needs to be an async gap to work around https://issues.chromium.org/u/1/issues/419746417.
// 一些其他导航已完成,但我们仍应保持运行。再启动一个假的导航以保持加载指示器运行。
// 需要一个异步间隙来解决 https://issues.chromium.org/u/1/issues/419746417。
setTimeout(startFakeNavigation, 20);
}
}
navigation.addEventListener('navigate', handleNavigate);
navigation.addEventListener('navigatesuccess', handleNavigateComplete);
navigation.addEventListener('navigateerror', handleNavigateComplete);

function startFakeNavigation() {
if (isCancelled) {
// We already stopped this Transition.
// 我们已经停止了这个过渡。
return;
}
if (navigation.transition) {
// There is an on-going Navigation already happening. Let's wait for it to
// finish before starting our fake one.
// 已经有一个导航正在进行。让我们等待它完成,再开始我们的模拟导航。
return;
}
// Trigger a fake navigation to the same page
// 触发一次到同一页面的伪导航
const currentEntry = navigation.currentEntry;
if (currentEntry && currentEntry.url != null) {
navigation.navigate(currentEntry.url, {
state: currentEntry.getState(),
// 指示路由器忽略此导航
info: 'react-transition', // indicator to routers to ignore this navigation
history: 'replace',
});
}
}

// Delay the start a bit in case this is a fast Transition.
// 稍微延迟开始,以防这是一次快速过渡。
setTimeout(startFakeNavigation, 100);

return function () {
isCancelled = true;
navigation.removeEventListener('navigate', handleNavigate);
navigation.removeEventListener('navigatesuccess', handleNavigateComplete);
navigation.removeEventListener('navigateerror', handleNavigateComplete);
if (pendingResolve !== null) {
pendingResolve();
pendingResolve = null;
}
};
}