Cover image for Angular2のPipeを使う上で開発者が知るべきたった1つのこと
angular2

Angular2のPipeを使う上で開発者が知るべきたった1つのこと

July 19, 2016

5 min read

mitsuruogMitsuru Ogawa

先日、学生向けに Todo ワークショップを開催した時の話です。 Angular1 のようにngForと Pipe を組み合わせて、リストのソート機能をつくろうとしたところ、初め上手く動かせませんでした。 StackOverFlow で解決策を見つけてなんとか動かすことはできたのですが、腑に落ちず後日改めて調べたところ、Pipe を使う上で知っておくべき事を知らなかったことに気づきました。

今回は Pipe を使う上で、これだけは最低限知っておくべき内容について紹介します。

tl;dr

  • 開発者が知るべきたった 1 つのことは、**「Angular2 の Pipe にはpureimpureの 2 種類がある」**ということ。
  • purePipe が想定通りのタイミングで動作しない時は、impureを使ってみるのも手。
  • ただし、Pipe でフィルタやソートを行うことはパフォーマンス上の懸念があるので、Component にて行うことを推奨します。

英語が読める人は本家のドキュメントを読んでください。

pureimpureの違い

まず、Pipe にはpureimpureの 2 つあるのですが、デフォルトはpureです。2 つの違いについて一言で表すとそれは**「Pipe が評価されるタイミング(反応する change detection)」**の違いです。下にその違いについて示します。

  • pure
    • プリミティブ型(String, Number, Boolean, Symbol)の値が変わった時
    • オブジェクト型(Date, Array, Function, Object)の参照が変わった時
  • impure
    • 常に評価

ここで大事なのはpureでは、オブジェクトや配列内部の変更は無視してしまうということです。(このことを本家ではpure changeと表現しています。) これは常に Deep check をすることを避け、パフォーマンスを向上させるために必要なことですが、うっかりこの事を知らないと Pipe が想定通りの動きをしない事態が容易に起こりえます。

impurePipe の作り方

impurePipe を作るためには、@Pipe宣言の部分でプロパティにpure: falseを指定することでできます。

@Pipe({
  name: 'impurePipe',
  pure: false
})
export class MyImpurePipe {}

非常に簡単なのですが、このとき「pureって何?」となるわけです。

まとめ

ではimpurePipe をガンガン使っていいのでしょうか?

本家のドキュメントに次の一文がありました。

No FilterPipe or OrderByPipe

Pipe でフィルタやソートは行わないでくれと行っています。本家ではこれらの機能を Component 側に移動することを推奨しています。 理由の 1 つとしてフィルタやソートを Pipe で行うために、必ず処理対象のオブジェクトの参照が必要となり、非常にコストが高い処理となり易いことが挙げられます。

Angular1 の時代からng-repeatと Filter を組み合わせてた場合、うっかり n×nの計算量となってしまい、パフォーマンス上の問題を出すことが多々ありました。 Angular2 でも同様に、ngForimpurePipe をうっかり組み合わせることは避けた方がいいと言えます。

おまけ