Angular v6.1で導入されるRouter Scrollerの紹介
こんにちは、lacoです。
Angularの次のマイナーアップデートで、久しぶりに新機能らしい新機能が増えます。 その名もRouter Scrollerです。 長くAngularを使っている人には涙が出るほど嬉しい待望の機能です。 この記事ではRouter Scrollerの紹介と、来週のbeta.1まで待てない!今すぐ試してみたい!という奇特な方のために、最新のビルドで試す方法も紹介します。
Router Scroller
Router Scrollerは、Angular Routerにスクロールに関連する機能を与えるものです。 Router Scrollerを使うと、次のようなことができます。
- ブラウザバックしたときに遷移前のスクロール位置に復元する
#foo
のようなフラグメント付きのURLで、対応するIDを持つ要素まで自動でスクロールする
どちらも、静的なHTMLページであればブラウザが自動的に行なってくれるものですが、Angular RouterによるSPAでも同じふるまいを簡単に導入できます。 それぞれについて紹介します。
Scroll Position Restoration
Router Scroller第一の機能は、スクロール位置の記憶と復元です。 Routerによるナビゲーションを行うたびに、その時点でのスクロール位置を記憶します。 そして、ブラウザの戻る操作で前の画面に遷移したときには、記憶したスクロール位置に自動的に復元します。 この復元処理はRouterによってタイミングが制御されているため、前の画面のルーティング処理が終わったあとにスクロールが移動します。 よって、先にスクロールが走ってしまい、あとからコンポーネントが描画されてしまい位置がずれる、ということはありません。
Anchor Scrolling
もうひとつの機能は、URLに#foo
のようなフラグメントが付いている場合、対応するIDを持つ要素があればそこまでスクロールする機能です。
これも静的なHTMLページではよく使われている機能ですが、Angularではブラウザが要素を探すタイミングがRouterによるコンポーネント生成より早いためうまくいきませんでした。
今回RouterがAnchor Scrolling機能を持ったことで、Angularアプリケーションであっても#foo
によるスクロールが可能になりました。
Routerによるナビゲーションだけでなく、リロードしても同様にスクロールしてくれます。
使い方
Scroll Position RestorationもAnchor Scrollingも、v6.1.0時点ではデフォルトで無効になっています。
そのため、有効にするにはRouterModule
に設定を行う必要があります。
RouterModule.forRoot
メソッドの第2引数のオプションに、scrollPositionRestoration
と anchorScrolling
が追加されています。
それぞれ、'enabled'
に設定すると機能が有効になります。これだけで完了です。
@NgModule({ imports: [ RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled', anchorScrolling: 'enabled', }) ], exports: [RouterModule] }) export class AppRoutingModule {}
Scroll Offset
Router Scrollerには、オフセットを指定することもできます。
ヘッダーがfixedやstickyな場合など、スクロール位置をずらしたい場合には、RouterModule.forRoot
メソッドの第2引数のオプションでscrollOffset
を設定します。
先程のAnchor Scrollingの例では、上部のヘッダーがstickyなので、y座標を64pxだけ下にずらしています。
@NgModule({ imports: [ RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled', anchorScrolling: 'enabled', scrollOffset: [0, 64] // [x, y] }) ], exports: [RouterModule] }) export class AppRoutingModule {}
今すぐ試すには
Router Scrollerはv6.1.0-beta.1からリリースに含められる予定です。
それより先に試したい方は、@angular/router
、@angular/common
、@angular/platform-browser
、@angular/platform-browser-dynamic
の4つをパッケージを開発版ビルドに置き換える必要があります。次のようなバージョン指定でよいでしょう。
"@angular/common": "angular/common-builds", "@angular/compiler": "^6.0.0", "@angular/core": "^6.0.0", "@angular/platform-browser": "angular/platform-browser-builds", "@angular/platform-browser-dynamic": "angular/platform-browser-dynamic-builds", "@angular/router": "angular/router-builds",
もっと知りたい
さらに詳しく知りたい方は、当該機能のコミット内容を読むと良いでしょう。
この記事のサンプルコードはGitHubで公開しています。