【Vue.js】JavaScriptでトランジションを実装する

## はじめに
仕事で使う事になったので1からVue.jsについて学んだ。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

## JavaScriptでトランジションを実装する
### JavaScriptでのトランジションの基本形
JavaScriptでのトランジション・アニメーションは、以下のように8つの**JavaScriptフック関数**を宣言する事で実装できる（beforeEnter, enter, ...のそれぞれは`methods: {}`内にそれぞれ定義する）。

```
<transition
      @before-enter="beforeEnter"
      @enter="enter"
      @after-enter="afterEnter"
      @enter-cancelled="enterCancelled"
      @before-leave="beforeLeave"
      @leave="leave"
      @after-leave="afterLeave"
      @leave-cancelled="leaveCancelled"
    >
  <div class="circle" v-if="show"></div>
</transition>
```

詳細は以下のコミットを参照。

https://github.com/yuta-katayama-23/intro-vuecli/commit/995393818cfca934700708e6a8bc5b1de659960a

### 実際にJavaScriptでトランジションを実装する
![ezgif.com-gif-maker (25).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/451b755e-c962-da70-a974-6545283b4b37.gif)
動画のソースコードは以下。

```vue:App.vue
<template>
  <div class="main">
    <!-- 省略 -->
    <button type="button" class="btn btn-primary me-1" @click="show = !show">
      切り替え
    </button>
    <br /><br />
    <transition
      :css="false"
      @before-enter="beforeEnter"
      @enter="enter"
      @leave="leave"
    >
      <div class="circle" v-if="show"></div>
    </transition>
    <!-- 省略 -->
  </div>
</template>

<script>
// 省略

export default {
// 省略
  methods: {
    beforeEnter(el) {
      // 現れる前
      el.style.transform = "scale(0)";
    },
    enter(el, done) {
      let scale = 0;
      const interval = setInterval(() => {
        el.style.transform = `scale(${scale})`;
        scale += 0.1;
        if (scale > 1) {
          clearInterval(interval);
          done();
        }
      }, 100);
    },
    leave(el, done) {
      // 消える時（イメージはtransitionのCSSの"-leave-active"の部分）
      let scale = 1;
      const interval = setInterval(() => {
        el.style.transform = `scale(${scale})`;
        scale -= 0.1;
        if (scale < 0) {
          clearInterval(interval);
          done();
        }
      }, 100);
    },
  },
};
</script>

<style scoped>
/* 省略 */

.circle {
  width: 200px;
  height: 200px;
  margin: auto;
  border-radius: 100px;
  background-color: deeppink;
}
</style>
```

- **`:css="false"`**<br>JavaScriptのアニメーションのみを有効化する時には、css属性にfalseをbindする<br>これにより以下のメリットが出る
  - 意図しないアニメーションの動きにならないようにする（name属性が未定義でもv-enter, ...は暗黙に存在するので）
  - CSSのトランジション・アニメーションの処理をskipさせられるのでパフォーマンスを向上させる

※注意として、`v-bind:css`で`false`をバインディングしており、falseはboolean型（文字列ではない）。

- **`done()`**<br>アニメーションが終わった事をVue.jsに伝えるための関数<br>上記の例では繰り返し非同期でトランジション・アニメーションを動かし、それが完了した事を伝える役割を担っている

ソースコード全体は以下。

https://github.com/yuta-katayama-23/intro-vuecli/commit/21121c2a81fc4cbcaa4bbc522f529f7d8ee30c05

### CSSトランジションとJavaScriptトランジションを併用するとどうなるか？
JavaScriptのトランジションの`enter()`、`leave()`のフック関数では、Vue.jsにトランジション・アニメーションが完了した事を伝えるための`done()`メソッドがあるが、これが呼ばれた場合はその時点で、CSSトランジションの動きが途中でも中断されてトランジションが完了になる。
`done()`メソッドがない場合、両方のトランジションが完了するまで動きが機能する。

### CSSトランジションとJavaScriptトランジションを併用している時の、トランジションクラスの適用・JavaScriptメソッドの実行が行われるタイミング
#### enter（要素が現れる時）
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/2913701c-c1f3-6258-d76e-71334f4190ba.png)

#### leave（要素が消える時）
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/5640e11b-3287-42bb-3561-1821721034ec.png)



## Vue.jsの勉強メモ一覧記事へのリンク
Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

- https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4