【Vue】トランジションを使って一定時間で自動でフェードアウトさせる

#やりたいこと
ボタンを押すと現れ、一定時間でふわっと消えるようなものを作りたい

例で使うHTMLは下記になります

 - いいねのボタンを押したら、いいねのメッセージが出てきて、３秒位かけてふわっと消える
 - 消えかけてるときに再度ボタンを押したら、もとに戻り再度フェードアウト始める
 - 効果はフェードアウトのみ

(一番下に動作サンプルおいています)

```html
<div id="app">
    <button>いいね</button>
    <div class="good">
        いいね
    </div>
    </span>
</div>
<style>
.good {
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    width: 150px;
    height: 50px;
    background-color: #2d2d2d;
}
</style>
```


#やりかた


##1. トランジションを使いフェードアウトさせる

アニメーションさせたいものを`<transition></transition>`で囲みます

```html
<div id="app">
    <button>いいね</button>
    <transition>
        <div class="good">
            いいね
        </div>
    </transition>
    </span>
</div>
```

次に、ボタンを押すと表示非表示を切り替えられるようにします
デフォルトが`false`の`show`というデータを用意しておきます
これが`true`のときに表示させます

```js:app.vue
new Vue({
    el: "#app",
    data: {
        show: false
    }
});
```

```html
<div id="app">
    <button @click="show = !show">いいね</button>
    <transition>
        <div v-show="show" class="good">
            いいね
        </div>
    </transition>
    </span>
</div>
```

`@click="show = !show"`でクリック時に真偽値を反転
`v-show="show"`で`true`のときだけ表示

これでクリックで表示と非表示は切り替わりました

次にフェードアウトです。
トランジションで囲んだものは、表示時に`enter`、非表示時に`leave`のスタイルのアニメーションを行います

![vue-transition](https://jp.vuejs.org/images/transition.png
)

今回はフェードアウトなので、`leave`を使います
透明度を３秒かけて1から0にしています

```css
.v-leave-active {
    transition: opacity 3s;
}

.v-leave {
    opacity: 1;
}

.v-leave-to {
    opacity: 0;
}
```

これで、クリックで表示、再度クリックでフェードアウトまではできました

<details><summary>ここまでの全体</summary>
<div>

```html:html
<div id="app">
    <button @click="show = !show">いいね</button>
    <transition>
        <div v-show="show" class="good">
            いいね
        </div>
    </transition>
    </span>
</div>
```

```css:css
.good {
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    width: 150px;
    height: 50px;
    background-color: #2d2d2d;
}

.v-leave-active {
    transition: opacity 3s;
}
.v-leave {
    opacity: 1;
}

.v-leave-to {
    opacity: 0;
}
```

```js:js
new Vue({
    el: "#app",
    data: {
        show: false
    },
    methods: {
        toggleBtn: function () {
            this.show = !this.show;
        }
    }
});

```

</div>
</details>

##2.自動で消えるように
今のままだと一回目表示で、二回目フェードアウトなので満たせていないです

解決策として、ボタンを押した際に、表示フラグを`true`にした後、自動で`false`にします


```js:js
new Vue({
    el: "#app",
    data: {
        show: false
    },
    methods: {
        fadeOut() {
            this.show = true;
            setTimeout(() => {
                this.show = false;
            }, 1);
        }
    }
});
```

```html
<div id="app">
    <button @click="fadeOut">いいね</button>
    <transition>
        <div v-show="show" class="good">
            いいね
        </div>
    </transition>
    </span>
</div>
```

`setTimeout`で１ミリ秒(1/1000秒)後に`false`にしています
これにより、`true`になり表示されるも、すぐ`false`状態になり、設定したフェードアウトが始まります

ちなみにアロー関数でthisが固定されているので、もし`function()`にしたい場合`bind`してください

```js
setTimeout(() => {
   this.show = false;
}, 1);

setTimeout(function() {
   this.show = false;
}.bind(this), 1);
```

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="natsume0718" data-slug-hash="GRqRWaZ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Vue Transition Fadeout">
  <span>See the Pen <a href="https://codepen.io/natsume0718/pen/GRqRWaZ">
  Vue Transition Fadeout</a> by natusme (<a href="https://codepen.io/natsume0718">@natsume0718</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>


よりよい方法が有りましたら教えていただけますと幸いです

<script async src="https://static.codepen.io/assets/embed/ei.js"></script>