開箱即用,TanStack Router 支援 雜湊滾動 (hash scrolling) 和 頁面頂部滾動 (top-of-page scrolling),無需任何額外設定。
預設情況下,滾動至頂部會模擬瀏覽器的行為,這意味著僅在成功導航後將 window 本身滾動至頂部。然而,對於許多應用程式來說,由於進階佈局的關係,主要的可滾動區域通常是巢狀的 div 或類似元素。如果您希望 TanStack Router 也為您滾動這些主要的可滾動區域,可以使用 routerOptions.scrollToTopSelectors 來指定目標選擇器:
const router = createRouter({
scrollToTopSelectors: ['#main-scrollable-area'],
})
const router = createRouter({
scrollToTopSelectors: ['#main-scrollable-area'],
})
這些選擇器會 與 window 一起處理,目前無法停用 window 的滾動行為。
滾動恢復是指在使用者返回頁面時恢復其滾動位置的過程。這通常是標準 HTML 網站的內建功能,但在 SPA 應用程式中可能難以實現,原因如下:
不僅如此,應用程式中常見的情況是擁有多個可滾動區域,而不僅僅是 body。例如,聊天應用程式可能有一個可滾動的側邊欄和一個可滾動的聊天區域。在這種情況下,您會希望獨立恢復這兩個區域的滾動位置。
為了解決這個問題,TanStack Router 提供了一個滾動恢復元件和鉤子 (hook),幫助您處理監控、快取和恢復滾動位置的過程。
其運作方式如下:
聽起來可能很複雜,但對您來說,只需這樣簡單設定:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
scrollRestoration: true,
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
scrollRestoration: true,
})
[!注意] > <ScrollRestoration /> 元件仍然可用,但已被標記為棄用 (deprecated)。
遵循 Remix 的滾動恢復 API,您也可以使用 getKey 選項自訂用於快取特定可滾動區域滾動位置的鍵 (key)。例如,這可以用於強制使用相同的滾動位置,無論使用者的瀏覽歷史如何。
getKey 選項會接收來自 TanStack Router 的相關 Location 狀態,並期望您返回一個字串以唯一識別該狀態的滾動測量值。
預設的 getKey 是 (location) => location.state.key!,其中 key 是為歷史記錄中的每個條目生成的唯一鍵。
您可以將滾動與路徑名稱 (pathname) 同步:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
getScrollRestorationKey: (location) => location.pathname,
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
getScrollRestorationKey: (location) => location.pathname,
})
您可以有條件地僅同步某些路徑,其餘則使用鍵:
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
getScrollRestorationKey: (location) => {
const paths = ['/', '/chat']
return paths.includes(location.pathname)
? location.pathname
: location.state.key!
},
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
getScrollRestorationKey: (location) => {
const paths = ['/', '/chat']
return paths.includes(location.pathname)
? location.pathname
: location.state.key!
},
})
有時您可能希望防止滾動恢復發生。為此,您可以在以下 API 中使用 resetScroll 選項:
當 resetScroll 設為 false 時,下一次導航的滾動位置將不會被恢復(如果是導航到歷史堆疊中的現有事件)或重置到頂部(如果是堆疊中的新歷史事件)。
大多數情況下,您無需特別操作即可讓滾動恢復正常工作。然而,在某些情況下,您可能需要手動控制滾動恢復。最常見的例子是 虛擬化列表 (virtualized lists)。
若要為整個瀏覽器視窗內的虛擬化列表手動控制滾動恢復:
function Component() {
const scrollEntry = useElementScrollRestoration({
getElement: () => window,
})
// 讓我們使用 TanStack Virtual 來虛擬化一些內容!
const virtualizer = useWindowVirtualizer({
count: 10000,
estimateSize: () => 100,
// 我們將滾動恢復條目中的 scrollY 傳遞給虛擬化器
// 作為初始偏移量
initialOffset: scrollEntry?.scrollY,
})
return (
<div>
{virtualizer.getVirtualItems().map(item => (
...
))}
</div>
)
}
function Component() {
const scrollEntry = useElementScrollRestoration({
getElement: () => window,
})
// 讓我們使用 TanStack Virtual 來虛擬化一些內容!
const virtualizer = useWindowVirtualizer({
count: 10000,
estimateSize: () => 100,
// 我們將滾動恢復條目中的 scrollY 傳遞給虛擬化器
// 作為初始偏移量
initialOffset: scrollEntry?.scrollY,
})
return (
<div>
{virtualizer.getVirtualItems().map(item => (
...
))}
</div>
)
}
若要為特定元素手動控制滾動恢復,您可以使用 useElementScrollRestoration 鉤子和 data-scroll-restoration-id DOM 屬性:
function Component() {
// 我們需要一個唯一的 ID 來為特定元素手動控制滾動恢復
// 它在您的應用程式中應盡可能唯一
const scrollRestorationId = 'myVirtualizedContent'
// 我們使用該 ID 來獲取此元素的滾動條目
const scrollEntry = useElementScrollRestoration({
id: scrollRestorationId,
})
// 讓我們使用 TanStack Virtual 來虛擬化一些內容!
let virtualizerParentRef: any
const virtualizer = createVirtualizer({
count: 10000,
getScrollElement: () => virtualizerParentRef,
estimateSize: () => 100,
// 我們將滾動恢復條目中的 scrollY 傳遞給虛擬化器
// 作為初始偏移量
initialOffset: scrollEntry?.scrollY,
})
return (
<div
ref={virtualizerParentRef}
// 我們將滾動恢復 ID 作為自訂屬性傳遞給元素
// 滾動恢復監視器會識別該屬性
data-scroll-restoration-id={scrollRestorationId}
class="flex-1 border rounded-lg overflow-auto relative"
>
...
</div>
)
}
function Component() {
// 我們需要一個唯一的 ID 來為特定元素手動控制滾動恢復
// 它在您的應用程式中應盡可能唯一
const scrollRestorationId = 'myVirtualizedContent'
// 我們使用該 ID 來獲取此元素的滾動條目
const scrollEntry = useElementScrollRestoration({
id: scrollRestorationId,
})
// 讓我們使用 TanStack Virtual 來虛擬化一些內容!
let virtualizerParentRef: any
const virtualizer = createVirtualizer({
count: 10000,
getScrollElement: () => virtualizerParentRef,
estimateSize: () => 100,
// 我們將滾動恢復條目中的 scrollY 傳遞給虛擬化器
// 作為初始偏移量
initialOffset: scrollEntry?.scrollY,
})
return (
<div
ref={virtualizerParentRef}
// 我們將滾動恢復 ID 作為自訂屬性傳遞給元素
// 滾動恢復監視器會識別該屬性
data-scroll-restoration-id={scrollRestorationId}
class="flex-1 border rounded-lg overflow-auto relative"
>
...
</div>
)
}
若要控制頁面間導航時的滾動行為,您可以使用 scrollBehavior 選項。這允許您將頁面間的過渡設為即時滾動,而非平滑滾動。滾動恢復行為的全域設定支援與瀏覽器相同的選項,包括 smooth、instant 和 auto(詳見 MDN)。
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
scrollBehavior: 'instant',
})
import { createRouter } from '@tanstack/solid-router'
const router = createRouter({
scrollBehavior: 'instant',
})
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.