Angular 4.0新機能シリーズ第4弾です。今回はcoreモジュールとcommonモジュールに入った変更について解説します。
coreモジュールの変更
coreモジュールにはDependency Injectionとテンプレートシンタックスに変更が入っています。
OpaqueTokenの廃止とInjectionToken<T>の導入
ひとつめはDependency Injectionに関する変更です。 これまでInjectionのキーとして使われていたOpaqueTokenですが、4.0ではdeprecatedとなり、5.0で廃止されることになりました。 代わりに、InjectionTokenというクラスが導入され、今後はこちらを使うことになります。
InjectionTokenはInjectする対象の型情報をジェネリックとして持つことができます。 この変更に伴ってInjectorにも変更が入っており、第1引数がInjectionTokenのときは戻り値の型が推論されるようになっています。 たとえば文字列を注入するときは次のように書きます。
/** これまで **/
const APP_NAME = new OpaqueToken('appName');
{
providers: [{ provider: APP_NAME, useValue: 'My Awesome App'}]
}
const appName = injector.get(APP_NAME) as string; // any型なのでキャストが必要
/** これから **/
const APP_NAME = new InjectionToken<string>('appName');
{
providers: [{ provider: APP_NAME, useValue: 'My Awesome App'}]
}
const appName = injector.get(APP_NAME); // APP_NAMEから自動的にstring型になる
多くの場合、明示的なキャストが不要になり、簡潔なコードを書けるようになるでしょう。 もしユニットテストのモックなどで、InjectionToken<T>と互換性のないものを注入したいときは、逆に明示的なキャストがないとコンパイルエラーになります。
ライフサイクルメソッドのinterface化
これは一種の破壊的変更になりえるのですが、これまで抽象クラスとして提供されていたOnInitやAfterViewInitなどが、インターフェースとして提供されるようになります。 公式ドキュメントやほぼすべてのガイドではimplements OnInitという書き方で解説しているのですが、もしextends OnInitと記述している人がいれば4.0からは動かなくなりますので注意してください。
<template>タグに関する仕様変更
これまでテンプレート中で<template>タグを使うとTemplateRefのインスタンスが生成され、再利用可能なテンプレート部品として使えるようにできました。 しかしその際にAngularは最終的なDOMの出力から<template>タグを除去してしまいます。 <template>タグはHTMLの標準要素であり、Web Componentsの普及や他のライブラリによるタグの利用もあるので、あまり好ましくない挙動でした。
これを解決するために、4.0では新しく<ng-template>というテンプレートシンタックスを導入しました。 これはこれまでの<template>タグとまったく同じ使い方で、TemplateRefへの参照を作成するためのタグです。 もちろんこれまでの<template>タグの利用も可能ですが、おそらく5.0アップデート時には完全な切り替えが行われます。 アプリケーション中で<template>タグを使っているところがあれば、早めに書き直しておきましょう。
ちなみに、2系と同じ<template>タグの動きを維持する挙動は無効にできます。 コンパイラのenableLegacyTemplateオプションがfalseに指定されていると、<template>タグは完全にAngularの干渉を受けなくなります。 JiTコンパイルのときはbootstrapModule関数の第2引数でコンパイラの設定ができます。
boostrapModule(AppModule, {
enableLegacyTemplate: false
});
AoTコンパイルのときは、tsconfig.jsonやAoTPluginなどのangularCompilerOptionsで設定できます。
{
"angularCompilerOptions": {
"enableLegacyTemplate": false
},
"compilerOptions": {}
}
Renderer周辺の変更
4.0でもっとも大きな変更は、DOMレンダリングの内部機構の完全刷新です。 これまで使われていたRendererに代わるRenderer2がフルスクラッチで実装され、4.0からはそちらが使われています。 より高速で軽量になっていますが、これまでRendererの深いAPIを使っていた開発者にとっては僅かな修正が必要かもしれません。
RootRendererクラスは完全に廃止されていますので、代わりにRendererFactory2を使います。 なお、RendererクラスはまだInjectして使用できますが、非推奨になり、内部的にはRenderer2に処理を委譲しています。 今後はRenderer2を使うようにしましょう。
commonモジュールの新機能
NgIfの改善以外にも、commonモジュールにはいくつかの新機能が追加されました。
NgComponentOutletの導入
ダイアログのような用途で、コンポーネントを動的にテンプレートに追加したいケースで、これまではViewContainerなどのAPIを用いていましたが、 4.0から専用のNgComponentOutletというディレクティブが追加されて簡単に書けるようになります。
NgComponentOutletはNgTemplateOutletと似ていて、次のように使います。
import { MyDialogComponent } from './my-dialog.component';
@Component({
template: `
<ng-container *ngComponentOutlet="dialogCmpType"></ng-container>
`
})
export class MyCmp {
dialogCmpType = MyDialogComponent;
}
注意としては、これまでと同様、動的に追加されるコンポーネントはNgModuleのentryComponentsに設定するのを忘れないようにしましょう。
詳しいAPIについてはAPIドキュメントを参考にしてください。
titlecaseパイプの追加
これまでuppercaseとlowercaseしか用意されていませんでしたが、単語の先頭だけを大文字にするtitlecaseパイプが追加されました。
まとめ
OpaqueTokenからInjectionToken<T>へ<template>から<ng-template>へNgComponentOutletで動的なコンポーネント生成titlecaseパイプの追加OnInitのインターフェース化Rendererのバージョンアップ
Angular 4.0 Features