mcpField
V
vue-router

vue-router

github.com/tanstack開発15.3k54 回インストール1 日前に更新
リポジトリ

vue-router について

Vueアプリ開発者向けに、TanStack RouterのVueバインディングを解説するガイドです。ファイルベースのルーティング、型安全なナビゲーション、コンポーザブルを扱い、ローダーは既定でクライアント側で実行されます。

主な機能

  1. 01ファイルベースのルーティング設定
  2. 02型安全なリンクとナビゲーション
  3. 03Vueルーターコンポーザブル
  4. 04ルートデータと検索パラメーター
  5. 05コード分割とエラー処理

活用シーン

  1. 01VueアプリでのTanStack Router設定
  2. 02型付きパラメーターを使ったルート構築
  3. 03未保存の変更がある場合の遷移ブロック

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/tanstack/router --skill vue-router

インストール後、Claude Code で/vue-routerを入力して読み込まれたか確認します。

詳細

Vue Router (@tanstack/vue-router)

このスキルは router-core を基盤としています。基本概念については、まず @tanstack/router-core#router-core をお読みください。

このスキルでは、TanStack Router の Vue 固有のバインディング、コンポーネント、コンポーザブル、セットアップについて説明します。

CRITICAL:TanStack Router の型は完全に推論されます。キャストも、推論された値への型注釈も行わないでください。

CRITICAL:TanStack Router はクライアントファーストです。ローダーはデフォルトでサーバーではなく、クライアント上で実行されます。

CRITICAL:ほとんどのコンポーザブルは Ref<T> を返します。スクリプト内では .value 経由でアクセスし、テンプレート内では自動的にアンラップされます。これが React 版との最大の違いです。

CRITICAL:@tanstack/vue-router と vue-router(公式の Vue ルーター)を混同しないでください。両者は API が異なる、まったく別のライブラリです。

セットアップ全体:Vite でのファイルベースルーティング

1. 依存関係をインストールする
npm install @tanstack/vue-router
npm install -D @tanstack/router-plugin @vitejs/plugin-vue-jsx
2. Vite プラグインを設定する
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    // MUST come before vue()
    tanstackRouter({
      target: 'vue',
      autoCodeSplitting: true,
    }),
    vue(),
    vueJsx(), // Required for JSX/TSX route files
  ],
})
3. ルートルートを作成する
// src/routes/__root.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/vue-router'

export const Route = createRootRoute({
  component: RootLayout,
})

function RootLayout() {
  return (
    <>
      <nav>
        <Link to="/" activeProps={{ class: 'font-bold' }}>
          Home
        </Link>
        <Link to="/about" activeProps={{ class: 'font-bold' }}>
          About
        </Link>
      </nav>
      <hr />
      <Outlet />
    </>
  )
}
4. ルートファイルを作成する
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/vue-router'

export const Route = createFileRoute('/')({
  component: HomePage,
})

function HomePage() {
  return <h1>Welcome Home</h1>
}
5. ルーターインスタンスを作成して型を登録する
// src/main.tsx
import { createApp } from 'vue'
import { RouterProvider, createRouter } from '@tanstack/vue-router'
import { routeTree } from './routeTree.gen'

const router = createRouter({ routeTree })

// REQUIRED — without this, Link/useNavigate/useSearch have no type safety
declare module '@tanstack/vue-router' {
  interface Register {
    router: typeof router
  }
}

const app = createApp(RouterProvider, { router })
app.mount('#root')

コンポーザブルリファレンス

すべてのコンポーザブルは @tanstack/vue-router からインポートします。ほとんどは Ref<T> を返します。スクリプト内では .value 経由でアクセスし、テンプレート内では自動的にアンラップされます。

useRouter() — TRouter を返します(Ref ではありません)
import { useRouter } from '@tanstack/vue-router'

const router = useRouter()
router.invalidate()
useRouterState() — Ref<T> を返します

ルーターの状態変更を購読します。状態全体を公開するため、パフォーマンスコストが発生します。マッチまたはロケーションには、useMatches と useLocation を使用してください。

import { useRouterState } from '@tanstack/vue-router'

const isLoading = useRouterState({ select: (s) => s.isLoading })
// Access: isLoading.value
useNavigate() — 関数を返します(Ref ではありません)
import { useNavigate } from '@tanstack/vue-router'

const navigate = useNavigate()

async function handleSubmit() {
  await saveData()
  navigate({ to: '/posts/$postId', params: { postId: '123' } })
}
useSearch({ from }) — Ref<T> を返します
import { useSearch } from '@tanstack/vue-router'

const search = useSearch({ from: '/products' })
// Access: search.value.page
useParams({ from }) — Ref<T> を返します
import { useParams } from '@tanstack/vue-router'

const params = useParams({ from: '/posts/$postId' })
// Access: params.value.postId
useLoaderData({ from }) — Ref<T> を返します
import { useLoaderData } from '@tanstack/vue-router'

const data = useLoaderData({ from: '/posts/$postId' })
// Access: data.value.post.content
useMatch({ from }) — Ref<T> を返します
import { useMatch } from '@tanstack/vue-router'

const match = useMatch({ from: '/posts/$postId' })
// Access: match.value.loaderData.post.title
その他のコンポーザブル
  • useMatches() — Ref<Array<Match>>。アクティブなルートマッチすべて
  • useRouteContext({ from }) — Ref<T>。beforeLoad のコンテキスト
  • useBlocker({ shouldBlockFn }) — 未保存の変更がある場合にナビゲーションをブロックします
  • useCanGoBack() — Ref<boolean>
  • useLocation() — Ref<ParsedLocation>
  • useLoaderDeps({ from }) — Ref<T>。ローダーの依存値
  • useLinkProps() — LinkHTMLAttributes を返します
  • useMatchRoute() — 関数を返します。この関数を呼び出すと Ref<false | Params> が返されます

コンポーネントリファレンス

RouterProvider
import { RouterProvider } from '@tanstack/vue-router'
// In createApp or template
<RouterProvider :router="router" />
Link

アクティブ状態をスコープ付きスロットで扱える、型安全なナビゲーションリンクです。

<Link to="/posts/$postId" :params="{ postId: '42' }">
  View Post
</Link>


<Link to="/about">
  <template #default="{ isActive }">
    <span :class="{ active: isActive }">About</span>
  </template>
</Link>
Outlet

マッチした子ルートのコンポーネントをレンダリングします。

Navigate

宣言的なリダイレクトです(onMounted でナビゲーションを実行します)。

Await

遅延データ用の非同期セットアップコンポーネントです。Vue の <Suspense> と組み合わせて使用します。

CatchBoundary

Vue の onErrorCaptured を使用するエラーバウンダリーです。

Html と Body

Vue 固有の SSR シェルコンポーネントです。

function RootComponent() {
  return (
    <Html>
      <head>
        <HeadContent />
      </head>
      <Body>
        <Outlet />
        <Scripts />
      </Body>
    </Html>
  )
}
ClientOnly

onMounted(ハイドレーション完了後)のみ子要素をレンダリングします。

<ClientOnly fallback={<div>Loading...</div>}>
  <BrowserOnlyWidget />
</ClientOnly>

Vue 固有のパターン

createLink によるカスタムリンクコンポーネント
import { createLink } from '@tanstack/vue-router'
import { defineComponent, h } from 'vue'

const StyledLinkComponent = defineComponent({
  setup(props, { slots, attrs }) {
    return () => h('a', { ...attrs, class: 'styled-link' }, slots.default?.())
  },
})

const StyledLink = createLink(StyledLinkComponent)
レンダー関数(h())

@tanstack/vue-router のすべてのコンポーネントは、内部で h() レンダー関数を使用します。ルートコンポーネントでは、SFC テンプレートとレンダー関数のどちらも使用できます。

MyRoute.component.vue に記述する SFC テンプレート(ユーザーコードで最も一般的):

<template>
  <div>{{ data.title }}</div>
</template>

<script setup>
import { useLoaderData } from '@tanstack/vue-router'
const data = useLoaderData({ from: '/posts/$postId' })
</script>
ルーターコンテキストを使った認証
import { createRootRouteWithContext } from '@tanstack/vue-router'

const rootRoute = createRootRouteWithContext<{ auth: AuthState }>()({
  component: RootComponent,
})

const router = createRouter({
  routeTree,
  context: { auth: authState },
})

// In a route — access via beforeLoad
beforeLoad: ({ context }) => {
  if (!context.auth.isAuthenticated) {
    throw redirect({ to: '/login' })
  }
}
コード分割のための Vue ファイル規約

autoCodeSplitting を使用すると、Vue ルートでは任意で分割ファイル規約を利用できます。これは必須ではなく、単一ファイルの .tsx ルートでも問題ありません。分割ファイルは、ルート設定とコンポーネントを分離する場合に便利です。

  • myRoute.ts — ルート設定(検索パラメーター、ローダー、beforeLoad)
  • myRoute.component.vue — ルートコンポーネント(遅延読み込み)
  • myRoute.errorComponent.vue — エラーコンポーネント(遅延読み込み)
  • myRoute.notFoundComponent.vue — 見つからない場合のコンポーネント(遅延読み込み)
  • myRoute.lazy.ts — 遅延読み込みされるルートオプション

よくある間違い

1. 重大:スクリプトブロックでの.valueの付け忘れ

コンポーザブルはRef<T>を返します。<script>内では.valueを介してアクセスします。テンプレートでは自動的にアンラップされます。

// WRONG — accessing Ref without .value in script
const params = useParams({ from: '/posts/$postId' })
console.log(params.postId) // undefined!

// CORRECT — use .value
const params = useParams({ from: '/posts/$postId' })
console.log(params.value.postId)
2. 高:vue-router(公式)との混同

@tanstack/vue-routerはvue-routerではありません。vue-routerの<router-view>、<router-link>、useRoute()、useRouter()は使用しないでください。

// WRONG — official vue-router imports
import { useRoute, useRouter } from 'vue-router'

// CORRECT — TanStack Vue Router imports
import { useMatch, useRouter } from '@tanstack/vue-router'
3. 高:beforeLoadまたはloaderでのVueフックの使用

beforeLoadとloaderはコンポーネントのセットアップ関数ではなく、通常の非同期関数です。Vueコンポーザブルは使用できません。代わりに、ルーターコンテキストを介して状態を渡してください。

4. 中:プラグイン対象の誤り

ルータープラグインの設定でtarget: 'vue'を指定する必要があります。デフォルトは'react'です。

関連項目

  • @tanstack/router-core#router-core — ドメイン固有のパターン(検索パラメーター、データ読み込み、ナビゲーション、認証、SSRなど)に関するすべてのサブスキル

コメント