vue-router
API
基本的な使い方
<!-- ここにマッチしたコンポーネントが描写される -->
<router-view></router-view>
<!-- リンクを張りたいときは -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
const Foo = { template: '<div>foo</div>' };
const Bar = { template: '<div>bar</div>' };
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
];
const router = new VueRouter({
routes,
});
var app = new Vue({
el: '#app',
router,
});
router-link
には、ルートによってrouter-link-exact-active
やrouter-link-active
といったクラスが自動的に設 定される。
コンポーネント側から vue-router を操作するには次のオブジェクトを使う。
this.$route
path
fullPath
params
query
hash
matched
- 詳細はドキュメント参照
this.$router
(===router
)go
push
back
forward
- 詳細はドキュメント参照
Dynamic Route Matching
次のようにすることで、ダイナミックルーティングを設定できる。
:username
や:post_id
の部分は、this.$route.params
としてコンポーネントに渡される。
const routes = [{ path: '/user/:username/post/:post_id', component: User }];
// /user/evan/post/123?page=2
//
// params => { username: 'evan', post_id: 123 }
// query => { page: 2 }
params の変更を検知する
params が変更されただけでは、コンポーネントは再作成されない(再利用される)。 つまりライフサイクルメソッドは発動しない。 これを検知したいときは次のようにする。
const User = {
watch: {
$route(to, from) {},
},
// もしくはナビゲーションガードを使う
beforeRouteUpdate(to, from, next) {},
};
様々なルート定義
vue-router はpath-to-regexpを使用しており、多様なルート定義ができる。詳細はドキュメントを参照。
優先順位
重複したルートが合った場合は、先に定義されている方が優先される。
Nested Routes
下記のように設定すると、User
コンポーネントの中に配置した<router-view />
の部分に指定したコンポーネントが描写される。
const routes = [
{
path: '/user/:id',
component: User,
children: [
{ path: '', component: UserHome },
{
path: 'profile',
component: UserProfile,
},
{
path: 'posts',
component: UserPosts,
},
],
},
];
Programmatic Navigation
router.push
router.push('home');
router.push({ path: 'home' });
router.push({ path: `/user/${userId}` });
router.push({ path: 'register', query: { plan: 'private' } });
// なお、pathを指定すると、paramsは無視される。
// paramsを使うときは、`path`の代わりに`name`を使うこと。
router.push({ name: 'user', params: { userId: 123 } });
router.replace
history に履歴を残さずにルートを変更する。その他はpush
と同じ。
router.go
router.go(1);
router.go(-1);
router.go(3);
Named Routes
ルートに名前をつけることができる。
routes = [
{
path: '/user/:userId',
name: 'user',
component: User,
},
];
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
Named Views
- サイドバーの内容をページによって変更したいときなどは、
router-view
に名前をつけることで対応する。 - 名前をつけなかった View には自動的に
default
という名前が与えられる。 component
ではなくcomponents
なので注意
<router-view></router-view>
<router-view name="a"></router-view>
<router-view name="b"></router-view>
routes = [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz,
},
},
];
Named View をネストする
例えば、次の例のように、/settings/profile
のときだけ特定のコンポーネントを表示したい場合
/settings/emails /settings/profile
+-----------------------------------+ +------------------------------+
| UserSettings | | UserSettings |
| +-----+-------------------------+ | | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | |
| | +-------------------------+ | | | +--------------------+ |
| | | | | | | | UserProfilePreview | |
| +-----+-------------------------+ | | +-----+--------------------+ |
+-----------------------------------+ +------------------------------+
<!-- UserSettings.vue -->
<router-view />
<router-view name="helper" />
{
path: '/settings',
// You could also have named views at the top
component: UserSettings,
children: [
{
path: 'emails',
component: UserEmailsSubscriptions
},
{
path: 'profile',
components: {
default: UserProfile,
helper: UserProfilePreview
}
},
]
}
Redirect and Alias
- リダイレクトするには次のようにする。
- なお、この場合、ナビゲーションガードはリダイレクト元には適用されないので注意。
routes = [
// 通常のリダイレクト
{ path: '/a', redirect: '/b' },
// Named Routeにリダイレクト
{ path: '/a', redirect: { name: 'foo' } },
// ファンクションを使ってリダイレクト
{
path: '/a',
redirect: (to) => {
// TODO: toがなんなのかよくわからない
// return redirect path/location here.
},
},
];
Alias
リダイレクトと異なり、history を変更せず、ただ単に表示する内容をpath
で指定したものに差し替える。
パスを変更するコストをかけずに、URL の構成を変えることができるので便利。
routes = [{ path: '/a', component: A, alias: '/b' }];
ルートに関する情報を、$route ではなく Props として渡す
パラメータ類を$route
で取得するとコンポーネントの再利用性・テスト性が低くなるので、props
を使って取得するほうがよい。
BAD
// コンポーネント
const User = {
template: '<div>User {{ $route.params.id }}</div>',
};
// vue-router設定
const router = new VueRouter({
routes: [{ path: '/user/:id', component: User }],
});
GOOD
// コンポーネント
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>',
};
// vue-router設定
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// Named Viewを使っている場合はそれぞれに指定する
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false },
},
],
});
props
に指定できる値は下記の 3 種類がある
- boolean
route.params
が props として渡される
- object
- そのオブジェクトがそのまま props として渡される
- function
- 計算結果のオブジェクトが props として渡される
- ルートが変更された時にのみ実行されるので、ステートフルにしないよう注意する
- 例:
(route) => ({ query: route.query.q }) }
HTML5 History Mode
- hash mode (デフォルト)
- history(HTML5) mode
HTML5 モードを使うには次のように設定する。
const router = new VueRouter({
mode: 'history',
});
HTML5 モードにした場合、サーバ側で、全てのルートへのリクエストに対しindex.html
を返すように設定しておく必要があるので注意する。サーバ別の設定方法はこちら
この設定を行うと、404 ページが表示されなくなるため、下記の設定を行っておくこと。もしくは、サーバー側で、存在しない URL の場合に 404 を返す設定を行うこと。
routes = [{ path: '*', component: NotFoundComponent }];
Navigation Guards
Global Guards
beforeEach
全てのルート変更をキャッチする。
router.beforeEach((to, from, next) => {});
to
移動先のRoute Objectfrom
移動元の Route Objectnext
処理を完了するファンクションnext()
ルートの変更が承認されるnext(false)
処理を中止し元のルートに戻るnext('/')
ornext({...})
別のルートに移る。オブジェクトとして渡せるもの一覧next(ErrorInstance)
処理を中断する。エラーはrouter.onError()
で拾える。
beforeResolve
router.beforeResolve
で登録する。beforeEach
との違いは次の通り。
- Route の変更が承認される直前に実行される。
- 全ての、in-Component Guard と、非同期コンポーネントが解決された後に実行される。
afterEach
Route 変更の後に呼ばれる。next
は無いので変更を止めることはできない。
router.afterEach((to, from) => {});
Per-Route Guard
Route 設定ごとのガード。beforeEnter
routes = [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {},
},
];
In-Component Guards
コンポーネントごとのガード
-
beforeRouteEnter
- そのコンポーネントを使う Route が承認される前に呼ばれる
this
でコンポーネントインスタンスにアクセスできない(作られる前だから)- インスタンスへアクセスするには
next
コールバックを使う。ナビーゲーションの確定後に実行される。next((vm) => {
// `vm` を通じてコンポーネントインスタンスにアクセス
});
-
beforeRouteUpdate
- そのコンポーネントを使う Route が変更された場合に呼ばれる
- 例)'/foo/1' => '/foo/2'
this
でコンポーネントインスタンスにアクセスできる
-
beforeRouteLeave
- そのコンポーネントを使う Route から、別の Route に移動する前に呼ばれる
this
でコンポーネントインスタンスにアクセスできる
const MyComponent = {
template: `...`,
beforeRouteEnter(to, from, next) {},
beforeRouteUpdate(to, from, next) {},
beforeRouteLeave(to, from, next) {},
};