# Vue.js の transition ってなに?

transition タグは主に「追加した時に、ふわっとフェードインさせたり」、 あるいは「削除した時に、ふわっとフェードアウトさせたり」する時に使うもの」のようです。

Vue は、DOM からアイテムが追加、更新、削除されたときにトランジション効果を適用するための方法を複数提供しています:
Enter/Leave とトランジション一覧 - Vue.js

# 1. 勘違い

transition タグは、  アニメーション全般に使えるタグではありません。  transition タグは、DOM の追加と削除の描画に特化したタグです。

白状すると  CSS の transition プロパティ  と、  Vue.js の transition タグ  を 区別できていませんでした。いま振り返ってみると致命的です笑

自分は最初、transition はタグとして専用に用意されているのだから、 相当すごいことをするのだろうと思いました。 そして「transition はアニメーション全般に対して使うもの」と勘違いして、沼にはまっていました。

結果、あさっての方向に向かって3万光年くらい進んでしまいました。 長文の質問を teratail にしたり、 まったく意味のない箇所で transition タグで囲んで 「transition 完全に理解した」と思って悦に浸っていました。 もはやキチガイです。

# 2. 使い方

以下の CodePen を元に話を進めます。

See the Pen Vue.js transition tag by niconico25 (@niconico25) on CodePen.

# Step 1. CSS を書く

はじめを v-enter, transition している間を v-enter-active , おわりを v-enter-to で記述してあげます。

コードは以下の様な具合です。

/* はじめ */
.v-enter {
  /* 最初は表示して欲しくないので 0 */
  opacity: 0;
}
/* transition している間 */
.v-enter-active {
  transition: opacity 1s
}
/* おわり */
.v-enter-to {
  /* 終わったら表示して欲しいので 1 */
  opacity: 1;
}

transition はちゃんとプロパティを指定してあげたほうがベターだそうです。 勉強になります。ありがとうございます。

# Step 2. HTML を書く

transition タグで enter と leave のアニメーションを付与したい DOM を1つだけ囲みます。

<div id="app">
  <transition> <!-- transition タグで囲みます。 -->
    <div v-if="show">
      Hello, world!
    </div>
  </transition>
  <button @click="show=!show">
    click
  </button>
</div>

# Step 3. Vue.js を書く

new Vue({
  el: '#app',
  data: {
    show: true,
  }
})

# 3. CSS クラス

「開始状態を v-enter, transition している期間中を v-enter-active , 終了状態を v-enter-to で記述してあげます。」と前節で書きました。 が、実際の CSS の適用のされ方は以下のような具合になります。

# ◯ .v-enter クラス

1. v-enter:
enter の開始状態。 要素が挿入される前に適用され、要素が挿入された 1 フレーム後に削除されます。

# ◯ .v-enter-active クラス

2. v-enter-active:
enter の活性状態。トランジションに入るフェーズ中に適用されます。 要素が挿入される前に追加され、トランジション/アニメーションが終了すると削除されます。 このクラスは、トランジションの開始に対して、期間、遅延、およびイージングカーブを定義するために使用できます。

# ◯ .v-enter-to クラス

3. v-enter-to:
バージョン 2.1.8 以降でのみ利用可能です。enter の終了状態です。 要素が挿入された1フレーム後に追加されます(同時に v-enter が削除されます) 、トランジション/アニメーションが終了すると削除されます。

ちょっとだけ訳がおかしかったので、こちらで修正したものを記述しています。

# 4. 補足

# ◯ .v-enter-to の省略

v-enter-to には opacity: 1 を設定していました。 これは規定値と同じです。 そのため、今回の例では v-enter-to を省略することができます。

.v-enter {
  opacity: 0;
}
.v-enter-active {
  transition: opacity 1s
}
/*
.v-enter-to {
  opacity: 1;
} 
*/

# ◯ 表示できる要素は直下の1つだけ

transition は「単一 要素/コンポーネントのトランジション」です。 そのため、transition タグ直下に同時に3つの要素を表示しようとしても、できません。

<div id="app">
  <!-- クリックすると show の true, false が切り替わります。 -->
  <button v-on:click="show=!show">click</button>

  <transition>
    <div v-if="show">Hello, world!</div> <!-- 表示される -->
    <div v-if="show">你好,世界!</div> <!-- 表示されない -->
    <div v-if="show">こんにちは、世界!</div> <!-- 表示されない -->
  </transition>
</div>

以下のコードで、表示される要素は、一番上の Hello, world! だけです。

See the Pen Vue.js transition tag - 2 by niconico25 (@niconico25) on CodePen.

transition タグの直下に2つ以上の DOM を書いて、表示を切り替えることはできます。 これだけだとなに言っているんだ?って感じですが、 詳細は公式サイトの「要素間のトランジッション」に記述されています。

# ◯ 名前をつけてあげたい

transition を1つの要素だけではなく、2つ以上の要素につけたい時があります。 そんなときには名前をつけて区別させてあげます。

<!-- 名前なし -->
<transition>
  <img src="./fig.jpg">
</transition>

<!-- 名前つき -->
<transition name="my-transition">
  <img src="./fig.jpg">
</transition>
/* 名前なし */
/* 頭に v- をつける */
.v-enter {
  opacity: 0;
}
.v-enter-active {
  transition: opacity 1s
}
.v-enter-to {
  opacity: 1;
}

/* 名前つき */
/* 頭に 名前- をつける  */
/* 名前-enter  */
.my-transition-enter {
  opacity: 0;
}
/* 名前-enter-active */
.my-transition-enter-active {
  transition: opacity 1s
}
/* 名前-enter-to */
.my-transition-enter-to {
  opacity: 1;
}

各クラスは、トランジションの名前が先頭に付きます。 <transition> 要素に名前がない場合は、デフォルトで v- が先頭に付きます。例えば、 <transition name="my-transition"> の場合は、 v-enter クラスではなく、my-transition-enter となります。
トランジションクラス - Vue.js

# 5. 属性

appear, v-cloak について見ていきます。

<transition appear>
  <img src="./fig.jpg" v-cloak>
</transition>
/* transition */
.v-enter {
  opacity: 0;
}
.v-enter-active {
  transition: opacity 1s
}
.v-enter-to {
  opacity: 1;
}

/* v-cloak */
[v-cloak] {
  display: none;
}

もし、ご興味がありましたら、 適当な jpg ファイルを1つ各自で用意して、 fig.png と名前をつけて、同じディレクトリに保存した上で、 ブラウザでスーパーリロードを連打して確認してくみてください。 CodePen で書くべきでした... orz

# ◯ appear 属性

appear 属性を書くと  ページを開いたときに  、ふわっと表示する動作を実装できます。 appear 属性を指定された transition タグは、ページを開いた時に、要素が追加されます。

ノードの初期描画時にトランジションを適用したい場合は、appear 属性を追加することができます:
Enter/Leave とトランジション一覧 - Vue.js

# ◯ v-cloak 属性

v-cloak 属性を使うと  ページを開いたときに  、 変な表示のされ方を避けることができます。 変な表示とは、Vue.js がコンパイルする前の要素です。 v-cloak は Vue インスタンスのが完了すると自動的に外される属性です。

v-cloak - API
このディレクティブは関連付けられた Vue インスタンスのコンパイルが終了するまでの間残存します。

v-cloak 属性で、はまった方の記事を見かけたので引用いたします。

v-cloak ディレクティブを使うときは、 インラインで display:none; のスタイルを書いちゃだめ。
v-cloakが効かない - Qiita

しかし、v-ifと組み合わせるとif判定のほうが優先され、 条件が真になった時点で要素を表示してしまう なので、v-cloakとv-ifの組み合わせはNG
v-cloakが効かない件 - ISSUS

# 6. 背景

Vue.js は主に DOM の操作、HTML に関わる機能を提供してくれていますが、 Vue.js の transition タグは DOM の装飾、CSS に関わる機能を提供してくれています。 transition タグだけちょっと仲間外れです。 なぜ transition タグが、存在するのでしょうか?

まず CSS のクラスの切り替えだけでも同じことができるらしいですが、 それだと色々と辛いらしいです。

CSS transitionで頑張らないVue.js transition - Qiita

CSSとクラス切り替えだけで行うトランジションのつらさ
これで実際に表示されるかと思いますが、以下のような問題があるかと思います。

  • 常にDOM上に要素自体は表示されるため、v-ifなどでシンプルに記述できず、記述がわかりづらくなる
  • コンポーネントなどの表示を切り分ける場合、 created() が表示前に実行されるため、 「開いた時にcreatedしたい」みたいなことができない

また jQuery を使っても辛いらしいです。

jQuery から Vue.js へのステップアップ - Qiita
display:none が付いてるので、切り替えのフェードインにはトランジションの代用でアニメーションを使用しました。 visibility などを使ってもいいけど、このへんの実装も CSS 大好きじゃないとつらくなってきます。

transition は、いわば糖衣構文ということでしょうか。 こういう文章はありがたいです...

# 7. おわりに

ここまで以下のように見てきました。

色々はまって大変でした笑 以上になります。ありがとうございました。

Last Updated: 11/27/2019, 10:40:32 PM
x 消す
銀河英雄伝説が無料!