VueRouterのuseRoute()とuseRouter()の違い

こんにちは!kossyです!




さて、今回はVueRouterのuseRouteとuseRouterの違いについて、
ブログに残してみたいと思います。



環境

@vue/cli 4.5.9
vue @3.0.4
npm 6.14.8
node 14.15.0


useRoute()は現在のルートを表す

useRoute()およびuseRouter()の定義元を見てみます。

/**
 * Returns the current route location. Equivalent to using `$route` inside
 * templates.
 */
export declare function useRoute(): RouteLocationNormalizedLoaded;
/**
 * Returns the router instance. Equivalent to using `$router` inside
 * templates.
 */
export declare function useRouter(): Router;

useRoute()は、

Returns the current route location.

現在のルートの場所を返します。

とのことなので、表示しているページのルートを返す関数のようですね。

RouteLocationNormalizedLoaded型を見てみます。

/**
 * {@link RouteLocationRaw} with
 */
export declare interface RouteLocationNormalizedLoaded extends _RouteLocationBase {
    /**
     * Array of {@link RouteLocationMatched} containing only plain components (any
     * lazy-loaded components have been loaded and were replaced inside of the
     * `components` object) so it can be directly used to display routes. It
     * cannot contain redirect records either
     */
    matched: RouteLocationMatched[];
}

_RouteLocationBaseをextendsしたinterfaceのようです。

_RouteLocationBaseの型定義を見ましょう。

/**
 * Base properties for a normalized route location.
 *
 * @internal
 */
export declare interface _RouteLocationBase {
    /**
     * Percentage encoded pathname section of the URL.
     */
    path: string;
    /**
     * The whole location including the `search` and `hash`. This string is
     * percentage encoded.
     */
    fullPath: string;
    /**
     * Object representation of the `search` property of the current location.
     */
    query: LocationQuery;
    /**
     * Hash of the current location. If present, starts with a `#`.
     */
    hash: string;
    /**
     * Name of the matched record
     */
    name: RouteRecordName | null | undefined;
    /**
     * Object of decoded params extracted from the `path`.
     */
    params: RouteParams;
    /**
     * Contains the location we were initially trying to access before ending up
     * on the current location.
     */
    redirectedFrom: RouteLocation | undefined;
    /**
     * Merged `meta` properties from all of the matched route records.
     */
    meta: RouteMeta;
}

useRoute(). で表示されるコード補完候補に出てくる値は_RouteLocationBaseの値のようですね。

また、RouteLocationNormalizedLoadedにはRouteLocationMatched[]型のmatchedというプロパティが定義されています。
こちらも見にいきましょう。

export declare interface RouteLocationMatched extends RouteRecordNormalized {
    components: Record<string, RouteComponent>;
}

RouteRecordNormalizedをextendsしたinterfanceで、Record型のcomponentsというプロパティを持っていますね。

なんとな〜く型定義が理解できたので、console.logで動作確認をしてみましょう。

const route = useRoute()

onMounted(async () => {
  console.log(`matched: ${route.matched.some((record: RouteLocationMatched) => record.meta.requiresAuth)}`)
  console.log(`path: ${route.path}`)
  console.log(`fullPath: ${route.fullPath}`)
  console.log(`query: ${route.query}`)
  console.log(`hash: ${route.hash}`)
  console.log(`name: ${String(route.name)}`)
  console.log(`params: ${route.params}`)
  console.log(`redirectedFrom: ${route.redirectedFrom}`)
  console.log(`meta: ${route.meta.title}`)
}

出力例
f:id:kossy-web-engineer:20210116162850p:plain

router.index.tsでルーティング定義時にmeta情報を与えているため、
route.meta.requiresAuthやtitleで値が取得できています。
redirectedFromがundefinedなのは、今回はリダイレクトではなく直接ページにアクセスしたため、
値が未定義の状態になっています。


useRouter()はVueRouterのインスタンスを返す

こちらも型定義を見に行ってみましょう。

/**
 * Router instance
 */
export declare interface Router {
    /**
     * @internal
     */
    /**
     * Current {@link RouteLocationNormalized}
     */
    readonly currentRoute: Ref<RouteLocationNormalizedLoaded>;
    /**
     * Original options object passed to create the Router
     */
    readonly options: RouterOptions;
    /**
     * Add a new {@link RouteRecordRaw | Route Record} as the child of an existing route.
     *
     * @param parentName - Parent Route Record where `route` should be appended at
     * @param route - Route Record to add
     */
    addRoute(parentName: RouteRecordName, route: RouteRecordRaw): () => void;
    /**
     * Add a new {@link RouteRecordRaw | route record} to the router.
     *
     * @param route - Route Record to add
     */
    addRoute(route: RouteRecordRaw): () => void;
    /**
     * Remove an existing route by its name.
     *
     * @param name - Name of the route to remove
     */
    removeRoute(name: RouteRecordName): void;
    /**
     * Checks if a route with a given name exists
     *
     * @param name - Name of the route to check
     */
    hasRoute(name: RouteRecordName): boolean;
    /**
     * Get a full list of all the {@link RouteRecord | route records}.
     */
    getRoutes(): RouteRecord[];
    /**
     * Returns the {@link RouteLocation | normalized version} of a
     * {@link RouteLocationRaw | route location}. Also includes an `href` property
     * that includes any existing `base`.
     *
     * @param to - Raw route location to resolve
     */
    resolve(to: RouteLocationRaw): RouteLocation & {
        href: string;
    };
    /**
     * Programmatically navigate to a new URL by pushing an entry in the history
     * stack.
     *
     * @param to - Route location to navigate to
     */
    push(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>;
    /**
     * Programmatically navigate to a new URL by replacing the current entry in
     * the history stack.
     *
     * @param to - Route location to navigate to
     */
    replace(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>;
    /**
     * Go back in history if possible by calling `history.back()`. Equivalent to
     * `router.go(-1)`.
     */
    back(): ReturnType<Router['go']>;
    /**
     * Go forward in history if possible by calling `history.forward()`.
     * Equivalent to `router.go(1)`.
     */
    forward(): ReturnType<Router['go']>;
    /**
     * Allows you to move forward or backward through the history. Calls
     * `history.go()`.
     *
     * @param delta - The position in the history to which you want to move,
     * relative to the current page
     */
    go(delta: number): void;
    /**
     * Add a navigation guard that executes before any navigation. Returns a
     * function that removes the registered guard.
     *
     * @param guard - navigation guard to add
     */
    beforeEach(guard: NavigationGuardWithThis<undefined>): () => void;
    /**
     * Add a navigation guard that executes before navigation is about to be
     * resolved. At this state all component have been fetched and other
     * navigation guards have been successful. Returns a function that removes the
     * registered guard.
     *
     * @example
     * ```js
     * router.beforeEach(to => {
     *   if (to.meta.requiresAuth && !isAuthenticated) return false
     * })
     * ```
     *
     * @param guard - navigation guard to add
     */
    beforeResolve(guard: NavigationGuardWithThis<undefined>): () => void;
    /**
     * Add a navigation hook that is executed after every navigation. Returns a
     * function that removes the registered hook.
     *
     * @example
     * ```js
     * router.afterEach((to, from, failure) => {
     *   if (isNavigationFailure(failure)) {
     *     console.log('failed navigation', failure)
     *   }
     * })
     * ```
     *
     * @param guard - navigation hook to add
     */
    afterEach(guard: NavigationHookAfter): () => void;
    /**
     * Adds an error handler that is called every time a non caught error happens
     * during navigation. This includes errors thrown synchronously and
     * asynchronously, errors returned or passed to `next` in any navigation
     * guard, and errors occurred when trying to resolve an async component that
     * is required to render a route.
     *
     * @param handler - error handler to register
     */
    onError(handler: _ErrorHandler): () => void;
    /**
     * Returns a Promise that resolves when the router has completed the initial
     * navigation, which means it has resolved all async enter hooks and async
     * components that are associated with the initial route. If the initial
     * navigation already happened, the promise resolves immediately.
     *
     * This is useful in server-side rendering to ensure consistent output on both
     * the server and the client. Note that on server side, you need to manually
     * push the initial location while on client side, the router automatically
     * picks it up from the URL.
     */
    isReady(): Promise<void>;
    /**
     * Called automatically by `app.use(router)`. Should not be called manually by
     * the user.
     *
     * @internal
     * @param app - Application that uses the router
     */
    install(app: App): void;
}

結構読み応えのある型定義だったので、今回はよく使うpushのみ説明します。。。(興味のある方は是非ご自身で動かしてみてください。)

ポピュラーな使い方としては、ページ遷移を実現したい時ですね。

const router = useRouter()

login(formData.email, formData.password)
  .then(() => {
    router.push('/')
    })
  .catch(() => {
    alert('メールアドレスかパスワードが間違っています。')
  })

ログインに成功したら、ルート(/)のページへ遷移しています。

他にも便利な使い方がたくさんあるので、公式Guideを参考にしてみてください。




勉強になりました。