Vueライフサイクルフックのマニアックな方~activated , deactivated , errorCaptured~

(こちらの記事はVue2の内容です)
以前社内ブログで投稿していた記事の再掲です。

少し前にVueとNuxtのライフサイクルフックについてをまとめましたが、
実はあちらの記事では解説していないVueのライフサイクルフックがありますので今回はそれらをまとめます。

# **なんの話だっけ？**

一応おさらいとして、

ライフサイクルフックについて解説した[記事](https://qiita.com/Yuto_Tatsumi/items/177e41b2de15869b8952
)から図を持ってきておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681767/8350a907-b49a-d7a2-210f-d8cf8a6bda7e.png)

この図のタイミングと名前を覚えておけば、画面表示までの好きなタイミングで好きな処理を挟めるっていうのがライフサイクルフックでした。

基本的な内容としては
図に載っている

- `beforeCreate`

- `created`

- `beforeMount`

- `mounted`

- `beforeUpdate`

- `updated`

- `boforeDestroy`

- `destroyed`

の意味とタイミングを掴んでおけば業務で困ることはあんまりないと思います。

(そもそもbeforeDestroyとかでさえ使ってるの僕は見たことないです。すごい複雑なプロジェクトだと使ったりするんでしょうね・・・)

で、今回はこの図には載ってないライフサイクルフックを補足的な立ち位置でまとめておこうと思います。

# **activatedとdeactivated**

こちらの二つもライフサイクルフックとして存在しています。

どんな時に出てくるやつかというのは一言で表すと、
「コンポーネントに[keep-alive](https://jp.vuejs.org/v2/api/#keep-alive)使ってる時などに効くやつ」です。

keep-aliveってなんやねんって人のために簡単に説明を挟んでおくと、

まず、タブが二つある画面を想像してください。タブはクリックされたタブに切り替わります。
一つ目のタブ(タブ1とする)には入力欄があり、そこに「たこやき」と入力します。
そして二つ目のタブ(タブ2とする)に移動してください。
そのまま一つ目のタブに戻ってください。
あなたの「たこやき」は消えてます。

そんな経験ないですか。普通に嫌ですよね。
keep-aliveは、そんな風に勝手に「たこやき」が消えるのを回避してくれます。

あなたの「たこやき」を守るために、「たこやき」をキャッシュしておくようコンポーネントに指示してくれるというようなやつです。

もう少しちゃんと説明すると、
keep-aliveを一つ目のタブを構成しているコンポーネントに仕込んでおけば(具体的にはkeep-aliveタグでコンポーネントを囲む)、
そのコンポーネントは、別のコンポーネントに切り替えられたとしても消滅することなく、
入力された文字列をコンポーネントで保持しといてくれますので、タブを何回移動しようが入力した文字列が消えないようにできるということです。
(さすがに親コンポーネントが消えたら消えるみたいですが・・・)

keep-aliveを詳しく知りたい方は[公式](https://jp.vuejs.org/v2/api/#keep-alive)を見てくださいませ。

で、本題なんですが、
activatedとdeactivatedはこのkeep-aliveが動いている時に効果を発揮します。

keep-aliveがあるコンポーネントに「たこやき」を保持し続けるように指示をしている場合に、
そのコンポーネントを再度呼び出された時、すなわち**活性化した時がactivated**です。
さっきの例で言うと、タブ2からタブ1に帰ってきた時ですね。

この時タブ1コンポーネントにactivatedを仕込んでおけば動いてくれます。

じゃあ、deactivatedはその逆です。
「たこやき」を保持させられているコンポーネントから、別のコンポーネントに移動した時、
すなわち**非活性化した時がdeactivated**です。
さっきの例だと、「たこやき」を持つタブ1からタブ2に移動したタイミングですね。

この時にタブ1コンポーネントにdeactivatedを仕込んでいればそこが動きます。

ちょっとややこしいこと言うと、
この時タブ2コンポーネントがkeep-aliveで囲まれていてかつ、activatedに処理を書いていればそこも同時に動きます。

# **errorCaptured**

こっちは比較的新しいライフサイクルフックらしいんですが、まぁ名前の通りエラーをキャッチした時のライフサイクルフックです。

もっと具体的には、**子コンポーネントで発生したエラーを親コンポーネントがキャッチしたタイミング**で動きます。
ちなみに少し気をつけないといけないのが、
親コンポーネント、子コンポーネント、孫コンポーネントくらいまであった時に、孫コンポーネントでエラーが発生したとします。

すると最初に子コンポーネントのerrorCapturedが動きます。
そして次に親コンポーネントのerrorCapturedが動きます。
もしさらに親がいればそこのerrorCapturedに行き、最終的にはVue.config.errorHandlerまでいきます。

このように子から親へとずっとエラーが伝播していくのは意識しておいてください。

意識的に伝播を止める(errorCapturedからの返り値をfalseにする)か、エラーが起きてひたすら親へ伝播していても困らない設計にする必要があります。
あと、エラー発生源の孫コンポーネントのerrorCapturedは動かないのもポイントですね。

それからerrorCapturedは基本的に3つの引数を構える形で書きます。

順番に、
1. 例外情報
2. 例外が発生したコンポーネント情報
3. 例外が発生し場所に関する情報を含む文字列
こんな感じです。

```js
~~~~

errorCaptured(err, vm, info) {
  // 例外情報を表示
  console.log(err)
  // 例外が発生したコンポーネント情報を表示
  console.log(vm)
  // 例外が発生し場所に関する情報を含む文字列を表示
  console.log(info)

  // エラーが伝播していかないようにfalseを返却。
  // 何もしないと親コンポーネントにエラーがいってしまう。
  // どこでもfalseを返して止めてなければ、このエラーはVue.config.errorHandlerに行き着く
  return false
}

~~~~
```

たいしてややこしくはないですが、意識して止めないと親にどんどん伝播しちゃうのは気をつけてください。

# **終わり**

以上、少しマニアックなライフサイクルフック3つでした。

メインのライフサイクルフックは[以前](https://qiita.com/Yuto_Tatsumi/items/177e41b2de15869b8952)紹介したものですし、実際そこさえ押さえておけば後は適宜調べれば問題ない気がします。

しかし今回の3つも知っておけば、わりかしライフサイクルマスターなのではないでしょうか。
是非実践で、おしゃれな使い方に役立ててください。

# **参考**

・[https://qiita.com/ksh-fthr/items/a9d1e4544c57f70e9b2b](https://qiita.com/ksh-fthr/items/a9d1e4544c57f70e9b2b)

・[Vueライフサイクルフック記事](https://johobase.com/vue-lifecycle/)

・[https://jp.vuejs.org/v2/api/#activated](https://jp.vuejs.org/v2/api/#activated)

・[https://jp.vuejs.org/v2/api/#keep-alive](https://jp.vuejs.org/v2/api/#keep-alive)

・[errorCapturedの参考記事](https://wonwon-eater.com/vue-error-log/)

・[errorCapturedの参考記事2](https://morimori-kochan.hatenablog.com/entry/2019/08/08/013409)