导航阻止是一种阻止导航发生的方式。如果用户尝试在以下情况下导航,则通常会这样做
在这些情况下,应向用户显示提示或自定义 UI,以确认他们是否要离开。
导航阻止为整个底层历史记录 API 添加了一个或多个“阻止器”层。如果存在任何阻止器,导航将通过以下方式之一暂停
有 2 种方法可以使用导航阻止
假设我们想要在表单为脏时阻止导航。我们可以通过使用 useBlocker hook 来做到这一点
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty()) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
},
})
// ...
}
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty()) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
},
})
// ...
}
shouldBlockFn 为您提供对 current 和 next 位置的类型安全访问
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
// always block going from /foo to /bar/123?hello=world
const { proceed, reset, status } = useBlocker({
shouldBlockFn: ({ current, next }) => {
return (
current.routeId === '/foo' &&
next.fullPath === '/bar/$id' &&
next.params.id === 123 &&
next.search.hello === 'world'
)
},
withResolver: true,
})
// ...
}
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
// always block going from /foo to /bar/123?hello=world
const { proceed, reset, status } = useBlocker({
shouldBlockFn: ({ current, next }) => {
return (
current.routeId === '/foo' &&
next.fullPath === '/bar/$id' &&
next.params.id === 123 &&
next.search.hello === 'world'
)
},
withResolver: true,
})
// ...
}
您可以在 API 参考中找到关于 useBlocker hook 的更多信息。
除了基于逻辑/hook 的阻止之外,还可以使用 Block 组件来实现类似的结果
import { Block } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
return (
<Block
shouldBlockFn={() => {
if (!formIsDirty()) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
}}
/>
)
// OR
return (
<Block shouldBlockFn={() => !formIsDirty} withResolver>
{({ status, proceed, reset }) => <>{/* ... */}</>}
</Block>
)
}
import { Block } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
return (
<Block
shouldBlockFn={() => {
if (!formIsDirty()) return false
const shouldLeave = confirm('Are you sure you want to leave?')
return !shouldLeave
}}
/>
)
// OR
return (
<Block shouldBlockFn={() => !formIsDirty} withResolver>
{({ status, proceed, reset }) => <>{/* ... */}</>}
</Block>
)
}
在大多数情况下,在 hook 中使用 withResolver: false 的 shouldBlockFn 函数中使用 window.confirm 就足够了,因为它会清楚地向用户显示导航已被阻止,并根据他们的响应解决阻止。
但是,在某些情况下,您可能想要显示一个自定义 UI,该 UI 故意减少干扰并且与您的应用程序的设计更加集成。
注意: 如果 withResolver 为 true,则 shouldBlockFn 的返回值不会解决阻止。
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
const { proceed, reset, status } = useBlocker({
shouldBlockFn: () => formIsDirty(),
withResolver: true,
})
// ...
return (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
}
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
const { proceed, reset, status } = useBlocker({
shouldBlockFn: () => formIsDirty(),
withResolver: true,
})
// ...
return (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
}
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty()) {
return false
}
const shouldBlock = new Promise<boolean>((resolve) => {
// Using a modal manager of your choice
modals.open({
title: 'Are you sure you want to leave?',
children: (
<SaveBlocker
confirm={() => {
modals.closeAll()
resolve(false)
}}
reject={() => {
modals.closeAll()
resolve(true)
}}
/>
),
onClose: () => resolve(true),
})
})
return shouldBlock
},
})
// ...
}
import { useBlocker } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
useBlocker({
shouldBlockFn: () => {
if (!formIsDirty()) {
return false
}
const shouldBlock = new Promise<boolean>((resolve) => {
// Using a modal manager of your choice
modals.open({
title: 'Are you sure you want to leave?',
children: (
<SaveBlocker
confirm={() => {
modals.closeAll()
resolve(false)
}}
reject={() => {
modals.closeAll()
resolve(true)
}}
/>
),
onClose: () => resolve(true),
})
})
return shouldBlock
},
})
// ...
}
与 hook 类似,Block 组件返回与渲染属性相同的状态和函数
import { Block } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
return (
<Block shouldBlockFn={() => formIsDirty()} withResolver>
{({ status, proceed, reset }) => (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
)}
</Block>
)
}
import { Block } from '@tanstack/solid-router'
function MyComponent() {
const [formIsDirty, setFormIsDirty] = createSignal(false)
return (
<Block shouldBlockFn={() => formIsDirty()} withResolver>
{({ status, proceed, reset }) => (
<>
{/* ... */}
{status === 'blocked' && (
<div>
<p>Are you sure you want to leave?</p>
<button onClick={proceed}>Yes</button>
<button onClick={reset}>No</button>
</div>
)}
</>
)}
</Block>
)
}
您的每周 JavaScript 新闻。每周一免费发送给超过 100,000 名开发者。